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);
}
}
@Override
protected 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();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCommunicateViewModel = ViewModelProviders.of(getActivity()).get(CommunicateViewModel.class);
}
@Nullable
@Override
public 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
文章评论