当前位置: 代码迷 >> 综合 >> Android架构组件(三)——ViewModel
  详细解决方案

Android架构组件(三)——ViewModel

热度:32   发布时间:2024-01-15 10:17:53.0

Android架构组件(三)——ViewModel

上一篇文章讲到了Android架构组件之LiveData(Android架构组件(二)——LiveData),现在我们再来看看另一个成员ViewModel。

ViewModel是什么?

?ViewModel,从字面上理解的话,我们也能想到它肯定是跟视图(View)以及数据(Model)相关的。正像它字面意思一样,它是负责准备和管理和UI组件(Fragment/Activity)相关的数据类,也就是说ViewModel是用来管理UI相关的数据的。同时ViewModel还可以用来负责UI组件间的通信,这一点后面我们会有例子说明。

为什么需要ViewModel?

?在看过前面两篇介绍Lifecycle和LiveData的内容后,这个问题的基本就不用回答了。既然ViewModel是用来管理和UI组件有关的数据的,而LiveData又是这些数据的持有类,所以在使用LiveData的时候,就自然想到要使用ViewModel了。另外从ViewModel的定义,我们也能看到ViewModel还可以用于UI组件间的通信,回想下当初面试官问你Fragment之间怎么通信的问题,掌握ViewModel后就多了一种高逼格的回答了。

ViewModel基本使用

?前面在讲解LiveData时,我们已经使用了ViewModel,所以它的基本使用,在这里就不在赘述了,忘了的同学可以重新去翻一翻Android架构组件(二)——LiveData。我们主要看下ViewModel的生命周期,以及它用于组件间通信的使用。

ViewModel生命周期

?我们看看ViewModel的生命周期,在官方文档中,用下面这张图来描述ViewModel的生命周期。

?上图是用Activity作为例子,左侧表示Activity的生命周期状态,右侧绿色部分表示ViewModel的生命周期范围。当屏幕旋转的时候,Activity会被recreate,Activity会经过几个生命周期方法,但是这个时候ViewModel还是之前的对象,并没有被重新创建,只有当Activity的finish()方法被调用时,ViewModel.onCleared()方法会被调用,对象才会被销毁。这张图很好的描述了是当Activity被recreate时,ViewModel的生命周期。

? 另外,有个注意的地方:在ViewModel中不要持有Activity的引用。为什么要注意这一点呢?从上面的图我们看到,当Activity被recreate时,ViewModel对象并没有被销毁,如果Model持有Activity的引用时就可能会导致内存泄漏。那如果你要使用到Context对象怎么办呢,那就使用ViewModel的子类AndroidViewModel吧。

用于组件间通信

? 下面我们看下ViewModel用于Fragment之间通信的例子。

/*** Created by shymanzhu on 2017/12/26.*/public class CommunicateViewModel extends ViewModel {
    private static final String TAG = "CommunicateViewModel";private MutableLiveData<String> mNameLiveData;public LiveData<String> getName(){
    if (mNameLiveData == null) {
    mNameLiveData = new MutableLiveData<>();}return mNameLiveData;}public void setName(String name){
    if (mNameLiveData != null) {
    Log.d(TAG, "setName: " + name);mNameLiveData.setValue(name);}}@Overrideprotected void onCleared() {
    super.onCleared();mNameLiveData = null;}
}
/*** Created by shymanzhu on 2017/12/26.*/public class FragmentOne extends Fragment {
    private CommunicateViewModel mCommunicateViewModel;public static FragmentOne getInstance(){
    return new FragmentOne();}@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);mCommunicateViewModel = ViewModelProviders.of(getActivity()).get(CommunicateViewModel.class);}@Nullable@Overridepublic View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_one, container, false);ButterKnife.bind(this, view);return view;}@OnClick(R.id.btn_set_name)void onViewClicked(View v){
    switch (v.getId()){
    case R.id.btn_set_name:mCommunicateViewModel.setName("Jane");break;}}
}
/*** Created by shymanzhu on 2017/12/26.*/public class FragmentTwo extends 
  相关解决方案