我有一个容器 Fragment,称它为 ContainerFragment
,它包含两个 fragment ,FragmentA
和 FragmentB
。 FragmentA
和 FragmentB
使用 ViewModelProviders.of 在
方法。onCreate()
方法中创建一个 ViewModel
(这个)
假设容器一次只能显示一个 fragment ,我正在使用 FragmentTransaction.replace()
方法在 FragmentA
和 FragmentB 之间切换
。在我的例子中,我展示了 FragmentA
,它创建了 FragmentA
ViewModel,然后一个 Action 触发 FragmentB
来替换 FragmentA
.现在,当我完成 FragmentB
时,我再次调用 replace 以显示 FragmentA
。这是我在替换 fragment 的方法中所做的检查:
if (fragmentA == null) {
fragmentA = FragmentA.newInstance();
}
FragmentTransaction ft = getChildFragmentManager().beginTransaction();
ft.replace(R.id.container_content, fragmentA, "my-tag");
ft.commit();
由于 FragmentA
是在第一次运行时创建的,因此它不会进入 if block 。但我注意到 FragmentA
的 onCreate()
返回了 ViewModel 的不同实例。我在 FragmentA
中有以下代码:
public void onCreate(Bundle sI) {
super.onCreate(sI);
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
Log.i("test", "ViewModel-> " + mViewModel.toString());
}
日志打印:
ViewModel-> com.myapp.MyViewModel@ed93f63
我第一次创建FragmentA
然后
ViewModel-> com.myapp.MyViewModel@ff3eee4
在我调用 ft.replace()
之后。
所以,我很困惑为什么 ViewModelProviders
会第二次返回 ViewModel
的不同实例,即使 FragmentA
是不为空(因为它没有进入 if block ,我假设它不为空)?
最佳答案
根据doc :
A ViewModel is always created in association with a scope (an fragment or an activity) and will be retained as long as the scope is alive. E.g. if it is an Activity, until it is finished.
ViewModel
的范围绑定(bind)到输入 Fragment/Activity 的范围。
- Activity:当它被销毁且不是由配置更改引起
- Fragment:当它被销毁且不是由配置更改引起时(即从
FragmentManager
中删除)
换句话说,当您将 FragmentA
替换为 FragmentB
时,该 FragmentA
将被销毁,因此其关联的 ViewModel
实例将被删除。
当您调用 ViewModelProviders.of(fragment)
获取 ViewModel
时,最后它会将此任务交给 ViewModelStore
,它存储我们的 ViewModel
实例。
让我们深入研究 source code androidx.fragment.app.Fragment-1.0.0
@CallSuper
public void onDestroy() {
mCalled = true;
FragmentActivity activity = getActivity();
boolean isChangingConfigurations = activity != null && activity.isChangingConfigurations();
if (mViewModelStore != null && !isChangingConfigurations) {
mViewModelStore.clear();
}
}
因此 ViewModel
实例因调用 mViewModelStore.clear();
而被删除
关于Android 在调用 ft.replace 时为同一 fragment 返回不同的 ViewModel 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51977021/