Проблема: моя ViewModel уничтожается, потому что я должен начать другую активность, пока она еще нужна(Это неизбежно новая (предоставляемая Android) активность.)
Справочная информация: у меня есть приложение, которое управляет взаимодействием между несколькими наборами данных.Он использует ViewModel в качестве кеша производительности, поскольку доступ к данным может быть медленным (например, за 10 секунд).В ViewModel не хранятся критические данные, но производительность была бы неприемлемой без кеша.Исходные данные находятся в файловой системе.
ViewModel работает точно так же, как и ожидалось, если я не проведу агрессивное тестирование и не включу опцию разработчика "Не сохранять действия" в качестве способа имитации нехватки памяти.По большому количеству логов я вполне уверен, что происходит (подробности ниже).У меня вопрос, если мне не хватает альтернативы тем, о которых я думал.
Сценарий:
- Приложение запускается и загружает ViewModel и запускает действие A. (AppCompatActivity toбыть точным.)
- Пользователь взаимодействует и решает изменить каталог, содержащий некоторые (не все) из кэшированных данных.Для этого требуется запустить встроенную в Android активность (D) «для результата» (чтобы получить новое имя каталога).Код для этого ниже.
- Если «Не сохранять действия» установлено , а не : выбор каталога работает нормально, а ViewModel выживает.(Эквивалентно: действие не уничтожено.)
- Если установлено «Не сохранять действия» (или система решает прекратить действие, пока пользователь находит новый каталог): Деятельность A уничтожается сразу после завершения новой операции (D)
onCreate
, и вызывается onCleared
ViewModel.
(Это тестирование на Oreo, но я сомневаюсь, что это имеет значение.)
Вот намерение, которое начинает новую деятельность.По-видимому, это стандартный способ поиска файла или каталога, и он отлично работает (вместе с onActivityResult
), чтобы получить новый каталог.
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED",true);
startActivityForResult(intent, REQUEST_DIR_LOOKUP);
Я экспериментировал с другим действием (назовите его B)где у меня есть код, который имеет ту же проблему, и не могу найти способ предотвратить очистку ViewModel в (4) выше.В случае поиска по каталогу (D) это даже не вариант изменить его.Это должно быть что-то, прежде чем начать поиск в каталоге.
В своей собственной Деятельности (B) я пытался использовать isFinishing()
в ViewModel's onDestroy()
, чтобы пропустить super.onDestroy
, с неудивительным результатом, что система выдает ошибку, super.onDestroy()
не звонил.Я также пытался заставить B onCreate
получить ViewModel от A (успешно, это тот же адрес), но A onCleared
все еще вызывается сразу после завершения B onCreate
(я надеялся на счетчик ссылок).(Это подтверждается сообщениями журнала.)
Я не вижу способа предотвратить разрушение ViewModel при уничтожении A в случае 4 выше.Исправить это было бы идеальным решением.Преобразование ViewModel в классический синглтон должно работать.Если не сказать «не делай этого» «Не занимайся делами», это мой лучший выбор?
Если я пойду с синглтоном, есть ли лучший способ увидеть onCleared
событие (когда я хочу уничтожить ViewModel), чем хак с использованием фиктивной ViewModel.onDestroy
слишком рано, чтобы быть полезным.
Неделей позже
Комментарии, хотя и полезны, на самом деле не решают основную проблему, которая "законсервирована""Действия не играют хорошо с ViewModel.Я надеялся, что я что-то пропустил, но, видимо, нет, и мне придется обойти то, что мне кажется ошибкой в дизайне.
Я думаю, что вижу несколько другую, детальную, но связанную проблему на Pie: «законсервированное» действие не учитывает текущее вращение (как это было во всех предыдущих версиях) (да, то же самоеактивность, как в примере кода).Это легко исправить в Activity, но требует его изменения, чего я стараюсь избегать, особенно для этого Activity, поскольку оно может меняться от релиза к релизу.