问题
Are ViewModels independent of activity/fragment lifecycles or just their configuration changes. When will they cease to exist and the subsequent onCleared() method called. Can the viewModel be shared with another Activity ?
A situation:
Activity1+viewModel1--->(rotation)--->Activity1+viewModel1
--->(launch Intent)--->Activity2+viewModel1
is this sharing possible and is it a good practice.
Also, since the app lifecycle callbacks, onPause->onStop->onDestroy is same for both
1.activity rotating and
2.when an Activity ends,
how is a ViewModel figuring out internally the right time to call onCleared and finally end its lifecycle.
Findings:
the ViewModel uses a holderFragment internally to hold an instance of the activity and uses the setRetainInstance method like fragments to account for configuration changes.
Source: dive-inside-of-androids-viewmodel-architecture-components
回答1:
Are ViewModels independent of activity/fragment lifecycles or just their configuration changes.
They are independent of configuration changes and are cleared when activity/fragment is destroyed.
Following is the lifecycle of ViewModel from official site:
Can the viewModel be shared with another Activity ?
You shouldn't do that with Activities. However fragments can share a ViewModel
using their activity scope to handle communication between them
回答2:
check method onDestroy() in Fragment.java
public void onDestroy() {
this.mCalled = true;
FragmentActivity activity = this.getActivity();
boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations();
if (this.mViewModelStore != null && !isChangingConfigurations) {
this.mViewModelStore.clear();
}
}
The variant isChangingConfigurations is true when the Activity rotates, the viewModelStore method clear() is not called.
When Activity is destroyed, isChangingConfigurations is false, the viewModelStore will be cleared.
回答3:
okay,through the source code,we know the ViewModel bind with HolderFragment.you can from the code in class ViewModelProviders to find it.
@MainThread
public static ViewModelProvider of(@NonNull FragmentActivity activity,
@NonNull Factory factory) {
checkApplication(activity);
return new ViewModelProvider(ViewModelStores.of(activity), factory);
}
next,in class HolderFragment on it's OnDestroy() you can find
@Override
public void onDestroy() {
super.onDestroy();
mViewModelStore.clear();
}
Last,open it,
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}
now ,maybe you have know it.just like the picture above.when the fragment finished,it cleared; when activity recreate,the fragment's onDestroy() will not be invoked,because
public HolderFragment() {
setRetainInstance(true);
}
hope it can help you.
回答4:
If you follow the trail (Check super class) AppCompatActivity --> FragmentActivity --> ComponentActivity
ComponentActivity observe the lifecycle state.
onDestory() calls at configuration change (such as screen rotation) but viewModel doesn't get destroy because of the following condition.
getLifecycle().addObserver(new GenericLifecycleObserver() {
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (!isChangingConfigurations()) {
getViewModelStore().clear();
}
}
}
});
来源:https://stackoverflow.com/questions/50983738/when-is-the-viewmodel-oncleared-called