2017-07-30 82 views
0

看来,只要您在支持片段管理器的事务中使用.replace()方法,就会重新创建ViewModel。这是故意的吗?片段实例本身没有改变,ViewModel将在旋转/配置更改期间(部分)保留。支持片段管理器.replace()和ViewModel

我看到以下场景:

  1. 获取视图模型REF(计数= 0),更新计数= 1,旋转数= 1,所谓的onCreate再次数= 0(查看模型重新创建)。
  2. 调用.replace()并重新创建视图模型(活动和片段实例不变)。

使用支持库26.0.0。

ViewModel在我的片段onCreate创建并可以被限制在Fragment

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

任何阐明,如果这是正常的一些轻?

+0

“片段实例本身不是CH老化“ - 这是什么意思?一个'ViewModel'被实现为你传入'ViewModelProviders.of()'的任何'FragmentActivity'或'Fragment'的子保留片段。 – CommonsWare

+0

在活动我有一个片段阵列和我只是片段之间交换所述阵列中(使用底部NAV): '片段= mapOf(id来片段等)' 再后来: ' supportFragmentManager.beginTransaction()。replace(R.id.fragmentContainer,fragment).commit()' 我可以看到片段引用是相同的(未被重新创建)。 – Luke

+0

如果我移动到活动范围,它可以正常工作。 'viewModel = ViewModelProviders.of(activity).get(DashboardViewModel :: class.java)' – Luke

回答

1

replace()当你制作不同的片段时,会被调用来调用。对于您拨打update()的同一个片段。

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

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

当你做create()时,它创建GUI的一切,所以很明显,这里再次发生ViewModel创建。

跟踪ViewModelcount是基于上面的说明。

ViewModel正在我的片段的onCreate中创建,并被限制为片段。这是片段的权力代表团。

1

至于@CommonsWare提到的viewmodel里的fragment里面的实例应该和Activity一样。

因此,活动里面,你应该做这样的事情

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

的片段里,你应该做这样的事情

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

在结果,他们会用同一个实例。

但是,如果您尝试使用它的片段里面

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

视图模型将在该片段中,当你旋转设备重建。 由于实例保存在片段内部而不是活动,当重新创建活动时,片段也将被重新创建,并且MyViewModel实例也会被重新创建。

尝试采取的例子来看看在主详细片段(这可能很容易解决您的问题)ViewModel in Android Developer

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上做了简单的主从模板

SimpleDetailActivity.java

SimpleDetailFragment.java