How do I use the new Saved State Module of ViewModel
For using Saved State module for View Model you have to add the androidx.lifecycle:lifecycle-viewmodel-savedstate
dependency to your project. This example has been written based on version 1.0.0-rc03
.
Please add the following line to your project Gradle file:implementation 'androidx.lifecycle:lifecycle-viewmodel-savedstate:1.0.0-rc03'
ViewModel implementation:
class SavedStateViewModel(private val state: SavedStateHandle) : ViewModel() {
val liveData = state.getLiveData("liveData", Random.nextInt().toString())
fun saveState() {
state.set("liveData", liveData.value)
}
}
Activity implementation:
class SavedStateActivity : AppCompatActivity() {
lateinit var viewModel: SavedStateViewModel;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding: ActivityStateBinding = DataBindingUtil.setContentView(this, R.layout.activity_state)
viewModel = ViewModelProvider(this, SavedStateViewModelFactory(this.application, this)).get(SavedStateViewModel::class.java)
binding.viewModel = viewModel
binding.lifecycleOwner = this
}
override fun onSaveInstanceState(outState: Bundle) {
if(::viewModel.isInitialized)
viewModel.saveState()
super.onSaveInstanceState(outState)
}
}
I have tested this code and it works fine.
I am adding an answer to this old post just in case someone might find it useful.
I managed to do it as follows:
- Add the following dependency to your "build.gradle (Module: app)" file
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
- Add
savedState: SavedStateHandle
property to the constructor of theViewModel
class SelectedTracksViewModel(private val savedState: SavedStateHandle) : ViewModel() {
companion object {
private const val SAVED_TRACK_INDEX = "savedTrackIndex"
}
private var trackIndex: Int
set(value) {
field = value
// Simply update the savedState every time your saved property changes
savedState.set(SAVED_TRACK_INDEX, value)
}
init {
trackIndex = savedState.get<Int>(SAVED_TRACK_INDEX) ?: 0
}
fun moveToNextTrack() {
trackIndex++
// Initially I was updating savedState here - now moved to setter
// Some more code here
}
}
Finally in the activity/fragment
private val selectedTracksViewModel: SelectedTracksViewModel by lazy {
ViewModelProvider(this).get(SelectedTracksViewModel::class.java)
}
And that's it. No need for SavedStateViewModelFactory
, simply add the savedState
property to your ViewModel
constructor and update it when tracked properties change. Everything else works as if you're not using savedState: SavedStateHandle
and this way is very similar to the traditional onSaveInstanceState(Bundle)
in activities/fragments.
Update: Initially I was updating savedState
after changing trackIndex
. This means one has to update savedState
every time saved properties are changed. This is a huge potential future bug if one forgets to add that line. A better and more robust pattern is to update the savedState
in the setter of the property.