Android ViewModel Save State (Kotlin)

March 5, 2020

NOTE:

  • ViewModel can survive configuration change (screen rotation)
  • To handle system-initiazted process death, you probably need to implement onSaveInstanceState / onRestoreInstanceState or use Saved State module for ViewModel.

NOTE: Save state will not function when the application exit via back button or kill by user via other means.

Dependencies

dependencies {
    def activity_version = "1.1.0"
    implementation "androidx.activity:activity-ktx:$activity_version"

    def fragment_version = "1.2.2"
    implementation "androidx.fragment:fragment-ktx:$fragment_version"

    def lifecycle_version = '2.2.0'
    // implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    // Lifecycles only (without ViewModel or LiveData)
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    // Saved state module for ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
}

Code

class MainActivity : AppCompatActivity() {

    private val viewModel by viewModels<MainViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        setSupportActionBar(toolbar)

        viewModel.getTestData().observer(this) {
            textView.text = it
        }

        button.setOnClickListener {
            viewModel.saveState()
        }
    }
}

NOTE: SavedStateViewModelFactory (previosly known as SavedStateVMFactory) automatically configured when using Activity 1.1.0, or Fragment 1.2.0.

class MainViewModel(val state: SavedStateHandle) : ViewModel() {
    fun saveState() {
        state.set("test", "TEST")
    }

    fun getTestData(): MutableLiveData<String> {
        return state.getLiveData<String>("test")
    }
}

Testing

In order to test if ViewModel Save State works, we need to simulate system-initialized process death.

One way of doing it is

  • Run app (Shift + F10) from Android Studio
  • Click home button on device to put into background
  • Click Stop (F2) from Android Studio

NOTE: There are other methods which I have yet to try.

On the device, find the app icon and launch again, the state value shall be restored.

The following method will not simulate system-initialized process death (thus state shall not be restored)

  • Click back button to exit app
  • Kill app on device via Overview button (Square icon)
  • Kill app via adb shell am force-stop APPLICATION_ID

References:

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.