Comments 15
setRetainInstance(true);
Биндинг модели во вьюшку — это хорошо, но иногда может быть избыточно.
setRetainInstance(true)
не избавляет вас от обязанности сохранять состояние, так как на не помогает в случаях когда Activity была уничтожена и затем восстановлена. Я вообще советую никогда эту опцию не использовать. Разве только в редких случаях, когда восстановление View крайне дорогая операция.Интересная проблема выискивается после того, как мы откроем другую активити и вернемся назад, а все введенные данные останутся, ибо при открытии и возврате не вызывается метод onCreate.Не вижу ни какой проблемы. При возвращении в предыдущую Activity она, в большинстве случаев, должна сохранять свое состояние.
Вы пишете, что при убийстве из-за ннхватки памяти нам не нужно сохранять данные.
имхо, правильное поведение, когда пользовиель не знает, что происходило с процессом пока он был в фоне и все его данные сохраняются если он явно не пожелал обратного (например, закрыв активити)
Осмелюсь предположить, что на самом деле ничего-то толком и не сохраняется, сохраняется только ссылка на ViewModel, которая потом восстанавливается. В javadoc-ах к Parcel
упоминается интересная особенность:
An unusual feature of Parcel is the ability to read and write active
- objects. For these objects the actual contents of the object is not
- written, rather a special token referencing the object is written. When
- reading the object back from the Parcel, you do not get a new instance of
- the object, but rather a handle that operates on the exact same object that
- was originally written.
То есть, фактически, ничего не сериализуется, просто если не надо передавать данные меджу процессами (а Parcelable в том числе было сделано для IPC), в целях оптимизации производительности где-то магически держится ссылка на объект ViewModel, который в свою очередь держит ссылки на все объекты внутри себя. Это можно проверить, убив активити (например, свернув его и нажав в Android Studio на панели Android Monitor кнопку "Terminate Application"). Если данные не сериализовались, а просто где-то держалась ссылка на ViewModel, данные не восстановлятся.
Это скорее предположение + немного смутных воспоминаний из своего опыта. Стоит проверить.
Caused by: java.lang.ClassCastException: com.quinque.aether.reactivemvvm.base.BaseViewModel cannot be cast to com.quinque.aether.reactivemvvm.ViewModel
На самом деле ваше решение ничем не отличается от того чтоб создать статическое поле и туда записывать вашу ViewModel на момент пересоздания Activity. Вся прелесть Parcelable что модель должна выживать даже когда Android убивает вашу Activity.
Да нет, что вы, лоадеры помогают в некоторой степени бороться с поворотами, но от нехватки ресурсов все так же не спасают. Я в последнее время решил не бороться с платформой, а подружиться с ней. Фактически, Теперь у меня при убийстве презентеры (у меня MVP, а не MVVM на текущем проекте, но сути это не меняет) умирают и пересоздаются вместе с активити/фрагментами. Все, что надо, сохраняю в Bundle. Как бонус, теперь не нужно проверять, прикреплена ли View к презентеру, потому что они не существуют раздельно, плюс поддерживается восстановление не только при смене ориентации, но и при смерти от нехватки ресурсов.
Теоретически может возникнуть ситуация, когда при пересоздании активити восстанавливается слишком много всего, тогда можно отключить пересоздание этой activity и обрабатывать ситуацию вручную (при восстановлении после нехватки памяти время не так критично, потому что пользователь покидал экран/приложение и не ждет моментального отклика) или сделать retain fragment, но на практике мне пока не приходилось такое делать даже на довольно нагруженных экранах.
Повороты экрана в Android без боли