【Jetpack日记(4)】ViewModel和LiveData
ViewModel介绍
关于ViewModel,根据官网开发文档介绍,它可以管理界面控制器(如 Activity 和 Fragment)的生命周期。Android 框架可能会决定销毁或重新创建界面控制器,以响应完全不受您控制的某些用户操作或设备事件。意思就是比如当Activity销毁或者重新创建的时候(比如屏幕选择),因配置更改而重新创建 Activity 后,新 Activity 必须重新提取用户列表。对于简单的数据,Activity 可以使用onSaveInstanceState()
和onCreate()
进行数据恢复。但是,一些较大的数据,就不太适合用通常的方法来进行恢复了。而ViewModel就可以帮助我们来解决这个问题。
LiveData介绍
根据官网开发文档说明,它是一个可以感知生命周期,就是和LifeCycle绑定的一个数据存储类,而且LiveData遵照观察者模式,当生命周期发生变化的时候,LiveData就会通知被观察的那些对象,这样就可以实现实时更新界面数据了,而且在生命周期结束的时候,也会自动进行销毁,因为通过LifeCycle进行绑定了,这样也不会发生内存泄露,也就不需要手动去处理生命周期的那些事件了。
ViewModel的基本使用
老样子,首先导入依赖,参考官方导入说明。
其实关于ViewModel和LiveData的基本使用,其实官网说明的很清楚了,我这里只是基本介绍一下,首先是在Activity中使用,我们需要创建一个类来继承ViewModel,这里的MutableLiveData其实就是Jetpack的另一个架构组件LiveData组件,具体用法我稍后再说。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> list;
public LiveData<List<User>> getUsers() {
if (list == null) {
list = new MutableLiveData<>();
loadUsers();
}
return list;
}
private void loadUsers() {
// Do an asynchronous operation to fetch users.
User user = new User();
user.setName("测试");
List<User> users = new ArrayList<>();
users.add(user);
list.setValue(users);
}
}
//JavaBean
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在Activity中,我们通过ViewModelProviders来获取和调用需要的ViewModel就好了,代码如下:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView;
textView = findViewById(R.id.test);
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getUsers().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
textView.setText(users.get(0).getName());
}
});
}
}
MainActivity运行结果
Fragment数据共享
两个Activity之间或者Fragment之间传递数据是很经常的事情,一般传递数据之间我们不是通过Intent,要不就是通过Bundle来进行数据的传递,我们其实也可以通过ViewModel来进行数据的传递,举个例子,比如在一个Fragment单击一个控件,然后进行数据传递,这个数据会显示在第二个Fragment上面,首先修改一下ViewModel
public class MyViewModel extends ViewModel {
private MutableLiveData<User> model = new MutableLiveData<>();
public void select(User user){
model.setValue(user);
}
public User getSelect(){
return model.getValue();
}
}
然后在两个Fragment中分别设置和获取,代码如下:
private MyViewModel myViewModel;
private void initView(View root) {
root.findViewById(R.id.text_home).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
User user = new User();
user.setName("传递Fragment");
myViewModel.select(user);
Toast.makeText(getActivity(),"已点击",Toast.LENGTH_SHORT).show();
}
});
}
然后在要获取的Fragment中进行获取就好了,通过getSelect()
方法。
final TextView textView = root.findViewById(R.id.text_dashboard);
myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
textView.setText(myViewModel.getSelect().getName());
Fragment传递结果
ViewModel的生命周期
ViewModel的生命周期如图,来源官网ViewModel对象存在的时间范围是获取ViewModel时传递给ViewModelProvider的Lifecycle。ViewModel将一直留在内存中,直到限定其存在时间范围的Lifecycle永久消失:对于Activity,是在Activity完成时;而对于Fragment,是在Fragment分离时。而且,通过ViewModel里的LiveData组件进行配合使用,还可以跟跟LifeCycle所进行关联,当调用LiveData的
observe()
进行更新的时候,就可以进行生命周期的感知了。ViewModel存在的时间范围是从您首次请求ViewModel直到Activity完成并销毁。observe所需要的参数
LiveData的基本使用
在ViewModel中,其实已经用到了LiveData,我们用的是MutableLiveData,它是LiveData的实现类,LiveData 是一个抽象类,它的实现子类有 MutableLiveData ,MediatorLiveData。在实际使用中,用得比较多的是 MutableLiveData。他常常结合 ViewModel 一起使用。LiveData的使用方法也很简单。
private MutableLiveData<String> mNameEvent = new MutableLiveData<>();
而进行监听的话,其实刚刚在ViewModel的基本使用中也说过了。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> list = new MutableLiveData<>();
public void setList(MutableLiveData<List<User>> list) {
this.list = list;
}
public MutableLiveData<List<User>> getList() {
return list;
}
}
//进行调用
MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
model.getList().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
textView.setText(users.get(0).getName());
}
});
如果说你想要传入参数的话,ViewModelProvider.of还有一个构造方法,它要传入的值就是ViewModelProvider.Factory,它是一个接口,我们可以这么写。
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> list = new MutableLiveData<>();
public MyViewModel(String key){
User user = new User();
user.setName(key);
list.setValue(new ArrayList<User>());
list.getValue().add(user);
}
public void setList(MutableLiveData<List<User>> list) {
this.list = list;
}
public MutableLiveData<List<User>> getList() {
return list;
}
public static class Factory implements ViewModelProvider.Factory {
private String key;
public Factory(String key) {
this.key = key;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return (T) new MyViewModel(key);
}
}
}
然后直接调用就好了
//第二个参数进行传入
MyViewModel model = ViewModelProviders.of(this, new MyViewModel.Factory("key")).get(MyViewModel.class);
model.getList().observe(this, new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
textView.setText(users.get(0).getName());
}
});
LiveData运行结果
关于自定义LiveData
public class UserLiveData extends LiveData<User> {
//监听数据
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super User> observer) {
super.observe(owner, observer);
}
//onPause ,onStop, onDestroy 也会调用onChanged的回调。
@Override
public void observeForever(@NonNull Observer<? super User> observer) {
super.observeForever(observer);
}
//回调该方法时,表示LiveData正在被使用。
@Override
protected void onActive() {
super.onActive();
}
//回调该方法时,表示他所有的 obervers 没有一个状态处理 STARTED 或者 RESUMED,注意,这不代表没有 observers。
@Override
protected void onInactive() {
super.onInactive();
}
}
关于自定义LiveData,主要是重写这几个方法,当LiveData处于活跃状态,可以调用onActive()
方法,当没有任何观察对象的时候,就是调用onActive()
方法,observeForever()
的区别就是在onPause、onStop、onDestroy的时候也会调用observe()
的onChange()
方法。