I am in the following scenario:
I have an OnboardActivity
which contains a ViewModel
, I can rotate this OnboardActivity
many times and the ViewModel
persist across configuration changes without issues.
However, if I launch another Activity(FirebaseAuthActivity)
on top of this one (OnboardActivity
) with startActivityForResult(...)
, and then in FirebaseAuthActivity
I rotate the device and press the back button. When the OnboardActivity
is brought to the top of the stack it recreates the ViewModel
instance again.
Is this the normal behavior of ViewModel
in architecture components?
Is there a way I can tell the OnboardActivity
to not finish when it is pop from the stack with a screen orientation different than the one it was saved?
It is because of the Android system destroys the activity and recreates it from scratch, and as the activity is recreated, the old resources and instances of various classes(ViewModelProvider in our case) are first destroyed on calling onDestroy() method and later recreated in onCreate() .
If we rotate the screen activity will recreate, but if we use ViewModel values will be retain.
E.g. if it is an Activity, until it is finished. In other words, this means that a ViewModel will not be destroyed if its owner is destroyed for a configuration change (e.g. rotation). The new instance of the owner will just re-connected to the existing ViewModel.
In android, we can use ViewModel to share data between various fragments or activities by sharing the same ViewModel among all the fragments and they can access everything defined in the ViewModel. This is one way to have communication between fragments or activities.
I have answered to a similar question here, This might help you to fix your self as of now.
This was a bug from an android framework. Bug details
The fix is available in 28.0.0-alpha3 and AndroidX 1.0.0-alpha3
But if you don't want to update to above versions now itself, Then you can solve like this (I know this is a bad solution but I didn't see any other good way)
In your activity override onDestroy method and save all the required fields to local variables before calling super.onDestroy. Now call super.onDestroy then Initialize your ViewModel again and assign the required fields back to your new instance of ViewModel
about isFinishing
Below code is in Kotlin:
override fun onDestroy() {
if (!isFinishing) { //isFinishing will be false in case of orientation change
val oldViewModel = obtainViewModel()
val requiredFieldValue = oldViewModel.getRequiredFieldValue()
super.onDestroy
val newViewModel = obtainViewModel()
if (newViewModel != oldViewModel) { //View Model has been destroyed
newViewModel.setRequiredFieldValue(requiredFieldValue)
}
} else {
super.onDestroy
}
}
private fun obtainViewModel(): SampleViewModel {
return ViewModelProviders.of(this).get(SampleViewModel::class.java)
}
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