Сохранение состояния активности с помощью onSaveInstanceState() и ViewModel

После прочтения этого у меня остались некоторые вопросы относительно ViewModels:

https://developer.android.com/topic/libraries/architecture/saving-states

Здесь говорится, что вы должны использовать комбинацию ViewModel для изменений конфигурации (например, поворота экрана) и использования onSaveInstanceState() для всех других случаев, когда действие уничтожается, а затем воссоздается, чтобы сохранить состояние пользовательского интерфейса.

Мой вопрос заключается в том, как мы узнаем способ восстановления состояния при вызове onCreate(Bundle) - должен ли я использовать ViewModel или я должен использовать пакет, полученный в качестве параметра? При изменении конфигурации также вызывается onSaveInstanceState(), и, очевидно, всегда вызывается onCreate().

Если я восстановлю состояние только из ViewModel, оно не всегда будет оставаться с правильными данными (поскольку активность могла быть уничтожена по другим причинам, кроме изменений конфигурации). Если я использую только пакет, который я сохраняю в onSaveInstanceState(), то зачем мне начинать с ViewModel?


person Yonatan Nir    schedule 23.02.2019    source источник


Ответы (1)


Я думаю, что хорошо думать об этих источниках как о цепочке. У вас есть 2 источника данных: ViewModel, который быстрее, но живет меньше, и сохраненное состояние экземпляра, которое медленнее, но живет дольше.

Правило простое — попробуйте использовать свою ViewModel и, если она не заполнена, используйте пакет из onSaveInstanceState().

Когда вы делаете val model = ViewModelProviders.of(this).get(MyViewModel::class.java) в onCreate(), вы можете проверить, получаете ли вы новый экземпляр viewModel. Затем, если это новый экземпляр (т. е. его поля данных пусты), вы можете получить некоторые основные данные из своего пакета, например идентификатор контента, и извлечь данные из бэкэнда или базы данных на основе этого идентификатора, заполнить им свою новую ViewModel и затем заполните свою активность из ViewModel (если вы используете LiveData, это будет очень естественно).

В следующий раз, когда вызывается onCreate, вы повторяете процесс, либо заполняя свою активность из ViewModel, либо заполняя свою ViewModel, используя данные в Bundle, а затем заполняя свою активность из своей ViewModel.

Обновление: на самом деле очень похожий подход описан в официальных документах. . Единственная разница в том, что вы передаете пакет в ViewModel, и он решает, нужно ли ему извлекать данные, я не говорил конкретно об этом механизме.

person TpoM6oH    schedule 27.02.2019
comment
Что, если, например, все, что у меня есть в ViewModel, — это просто примитивы, которые инициализируются значением по умолчанию? Я не смогу сказать, связано ли это с тем, что экземпляр является новым, или это просто правильные значения. В любом случае, в целом ваше предложение звучит как обходной путь. - person Yonatan Nir; 28.02.2019
comment
Что ж, в этом конкретном случае вам нужно будет реализовать какое-то поле, которое будет указывать, что ваша ViewModel не является вновь созданной, или добавить некоторые данные в ваш пакет состояния и использовать его. Если у вас есть только куча примитивов для сохранения, вы не получите многого от использования ViewModel, в этом случае просто реализуйте состояние экземпляра и используйте его. ViewModel помогает вам сохранять сложные загруженные данные или данные, созданные пользователем. - person TpoM6oH; 28.02.2019
comment
Также проверьте обновление ответа, оно ссылается на официальный подход. - person TpoM6oH; 28.02.2019
comment
Итак, насколько я понимаю, он также просто говорит, что вы должны проверить, есть ли уже необходимые данные ... нет ли какого-то системного флага, который сообщает вам причину, по которой вы находитесь в onCreate? Или, может быть, флаг, сообщающий вам, была ли только что создана ViewModel или нет? - person Yonatan Nir; 01.03.2019
comment
Я думаю, что фреймворк не вызывает конструктор аргументов для ViewModel, когда вы впервые создаете его с помощью ViewModelProviders, поэтому вы можете использовать это как индикатор того, что ViewModel является новым. - person TpoM6oH; 01.03.2019