Guess I'm missing something obvious here but... I'm storing data in uiModel
in the DiaryViewModel class, and since I use architecture components I'm expecting the data to be retained through screen rotation - but it doesn't. I'm blind to why.
Here's a stripped down fragment
class DiaryFragment: Fragment() {
private lateinit var viewModel: DiaryViewModel
override onCreateView(...) {
viewModel = ViewModelProviders.of(this).get(DiaryViewModel::class.java)
viewModel.getModel().observe(this, Observer<DiaryUIModel> { uiModel ->
render(uiModel)
})
}
}
And the corresponding view model.
class DiaryViewModel: ViewModel() {
private var uiModel: MutableLiveData<DiaryUIModel>? = null
fun getModel(): LiveData<DiaryUIModel> {
if (uiModel == null) {
uiModel = MutableLiveData<DiaryUIModel>()
uiModel?.value = DiaryUIModel()
}
return uiModel as MutableLiveData<DiaryUIModel>
}
}
Can any one see what's missing in this simple example? Right now, uiModel
is set to null
when rotating the screen.
Fragments — Scenario 3: Activity with retained Fragment is rotated. The fragment is not destroyed nor created after the rotation because the same fragment instance is used after the activity is recreated. The state bundle is still available in onActivityCreated .
If we rotate the screen activity will recreate, but if we use ViewModel values will be retain.
ViewModel objects are automatically retained during configuration changes so that data they hold is immediately available to the next activity or fragment instance. FYI: You can use ViewModel to preserve UI state only during a configuration change, nothing else as explained perfectly in this official doc.
ViewModel is responsible for holding and processing all the data needed for the UI. It should never access your view hierarchy (like view binding object) or hold a reference to the activity or the fragment.
The issue was with how the activity was handling the fragment creation. MainActivity was always creating a new fragment per rotation, as in
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportFragmentManager
.beginTransaction()
.replace(overlay.id, DiaryFragment.newInstance())
.commit()
}
But of course, it works much better when checking if we have a saved instance, as in
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager
.beginTransaction()
.replace(overlay.id, DiaryFragment.newInstance())
.commit()
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With