Looking through why saving navigation state and screen state is important for users and developers, and what "edge-case" looking behaviors we need to take into consideration when developing Android applications.
foreground, the app must restore the preserved state and any significant stateful transaction that was pending, such as changes to editable fields, game progress, menus, videos, and other sections of the app.
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.zhuinden.processdeathexample, PID: 3601 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.zhuinden.processdeathexample/com.zhuinden.processdeathexample.SecondA ctivity}: kotlin.UninitializedPropertyAccessException: lateinit property myObject has not been initialized at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) Caused by: kotlin.UninitializedPropertyAccessException: lateinit property myObject has not been initialized at com.zhuinden.processdeathexample.ObjectHolder.getMyObject(ObjectHolder.kt:4) at com.zhuinden.processdeathexample.SecondActivity.onCreate(SecondActivity.kt:12) Expecting Singletons / statics to survive
property has not been initialized at xxx.ui.IncidentScreenFragment.showData(IncidentScreenFragment.kt:78) at xxx.ui.home.HomeActivity.filterData(HomeActivity.kt:110)
managed by the system on Android out of the box* – Empty ctor + using intent extras / fragment arguments • Screen state is partially managed by the system – Views with IDs have their state persisted – Complex state (f.ex. RecyclerView selection) are not persisted automatically – Dynamically added views should be recreatable
size limit – Data should be fetched asynchronously, off the UI thread • Transient state – „Loading” state: computed from progress of side- effect („something is happening”, but is it really?)
come from elsewhere val personFilter: String = "", val unhandledError: ErrorType? = null // enum or sealed class ): Parcelable ...but is this really necessary?
or when observed • Jetpack: store LiveData inside ViewModel, and expose it to observers – fetch begins when observed • Data can be loaded via a Transformation chain from a MutableLiveData that stores the state – changes trigger new data load • Note: LiveData is analogous with BehaviorRelay
class MainViewModel( private val sportDao: SportDao private val handle: SavedStateHandle ): ViewModel() { private val _selectedSportId = handle.getLiveData("selectedSportId") private val _selectedPosition = handle.getLiveData("selectedPosition") val sport = _selectedSportId.switchMap { sportDao.getSport(it) } val selectedPosition: LiveData<Int> get() = _selectedPosition }
with LiveData (Android Dev Summit '18) https://www.youtube.com/watch?v=2rO4r-JOQtA Google I/O Day 2: What’s new in Architecture Components https://www.youtube.com/watch?v=Qxj2eBmXLHg&list=PLOU2XLYxms ILVTiOlMJdo7RQS55jYhsMi&index=29