1

看来,每当您.replace()在事务中使用 Support Fragment Manager 中的方法时,都会重新创建 ViewModel。这是故意的吗?Fragment 实例本身没有改变,并且 ViewModel 将在旋转/配置更改期间(部分)保留。

我看到以下情况:

  1. 获取 View model ref (count = 0),更新 count = 1,rotate,count = 1,再次调用 onCreate和 count = 0(重新创建视图模型)。
  2. 调用.replace()和视图模型被重新创建(活动和片段实例不变)。

使用支持库 26.0.0。

ViewModel正在我的片段中创建,范围onCreateFragment

viewModel = ViewModelProviders.of(this).get(DashboardViewModel::class.java)

如果这是正常的,有人能说明一下吗?

4

2 回答 2

3

正如@CommonsWare 提到的,viewmodel里面的实例fragment应该在Activity.

因此,在 Activity 里面,你应该做这样的事情

MyViewModel vm = ViewModelProviders.of(this).get(MyViewModel.class);

在 Fragment 里面,你应该做这样的事情

MyViewModel vm = ViewModelProviders.of(getActivity()).get(MyViewModel.class);

结果,他们将使用相同的实例。

但是,如果您尝试在片段中使用它

MyViewModel vm = ViewModelProviders.of(this).get(MyViewModel.class);

当您旋转设备时,Viewmodel 将在片段中重新创建。由于实例保存在片段而不是活动中,因此当重新创建活动时,片段也将被重新创建,并且 MyViewModel 实例。

尝试查看有关主详细信息片段的示例(这可能很容易解决您的问题)Android Developer 中的 ViewModel

public class MasterFragment extends Fragment {
    private SharedViewModel model;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        itemSelector.setOnClickListener(item -> {
            model.select(item);
        });
    }
}

public class DetailFragment extends LifecycleFragment {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SharedViewModel model = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
        model.getSelected().observe(this, { item ->
           // update UI
        });
    }
}

我还在 github 上做了简单的 Master Detail 模板

SimpleDetailActivity.java

SimpleDetailFragment.java

于 2017-09-28T05:37:23.883 回答
2

replace()当您制作不同的片段时,应该会调用它。对于您调用的同一片段update()

replace()方法意味着您可以用具有不同布局(物理结构)的不同片段替换当前片段。你甚至不能保证它从前一个片段使用的相同内存开始。ViewModel是整个容器的一种布局。因此,对于具有不同物理结构和(可能具有不同内存——我正在写可能是因为您也可以用相同的片段替换)的对象,您必须重新创建不同的对象ViewModel定义它的容器。这是因为一个ViewModel对象指向一个引用容器,下次你有不同的片段时,你的片段容器由 ViewModel 定义在其他地方,所以你需要另一个ViewModel对象来指向那个片段容器。

但是当你这样做时update(),或者rotate(),你保证更新片段的内存空间可以减少/增加,但它的起始内存仍然保持不变。所以不需要创建ViewModel. 这是因为您的旧ViewModel对象正在引用同一个旧片段的容器。

当您执行 create() 时,它会创建 GUI 一切,因此显然会ViewModel再次发生创建。

的跟踪ViewModel count是基于上面的解释。

ViewModel 是在我的片段的 onCreate 中创建的,并且范围仅限于片段。这是对片段的一种权力委派。

于 2017-07-30T19:03:44.047 回答