简单地说,LiveData是一个数据持有类。它具有以下特点:
数据可以被观察者订阅;
能够感知组件(Fragment、Activity、Service)的生命周期;
只有在组件出于激活状态(STARTED、RESUMED)才会通知观察者有数据更新;
PS: 文中提到的“组件”皆指实现了LifecycleOwner接口Fragment、Activity。
为什么需要LiveData
从LiveData具有的特点,我们就能联想到它能够解决我们遇到的什么问题。LiveData具有以下优点:
能够保证数据和UI统一
这个和LiveData采用了观察者模式有关,LiveData是被观察者,当数据有变化时会通知观察者(UI)。
减少内存泄漏
这是因为LiveData能够感知到组件的生命周期,当组件处于DESTROYED状态时,观察者对象会被清除掉。
当Activity停止时不会引起崩溃
这是因为组件处于非激活状态时,不会收到LiveData中数据变化的通知。
不需要额外的手动处理来响应生命周期的变化
这一点同样是因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。
组件和数据相关的内容能实时更新
组件在前台的时候能够实时收到数据改变的通知,这是可以理解的。当组件从后台到前台来时,LiveData能够将最新的数据通知组件,这两点就保证了组件中和数据相关的内容能够实时更新。
针对configuration change时,不需要额外的处理来保存数据
我们知道,当你把数据存储在组件中时,当configuration change(比如语言、屏幕方向变化)时,组件会被recreate,然而系统并不能保证你的数据能够被恢复的。当我们采用LiveData保存数据时,因为数据和组件分离了。当组件被recreate,数据还是存在LiveData中,并不会被销毁。
资源共享
通过继承LiveData类,然后将该类定义成单例模式,在该类封装监听一些系统属性变化,然后通知LiveData的观察者,这个在继承LiveData中会看到具体的例子。
简单说下liveData使用
1创建一个类实现ViewModel,定义一个方法获取liveData
/**
* liveData是个抽象类 ,可以理解为一个能感知生命周期的仓库
* mutableLIveData 是他的实现类
*/
public class MyViewModel extends ViewModel {
//注意使用static修饰 源码直接通过类获取
private static MutableLiveData> mutableLiveData;
//获取仓库
public MutableLiveData> getLiveData() {
if (mutableLiveData == null) {
mutableLiveData = new MutableLiveData<>();
}
return mutableLiveData;
}
}
2定义一个bean类
public class Bean {
String name;
public Bean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3在activity中使用
订阅消息代码
//调用系统API获取 viewModel
MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
liveData = myViewModel.getLiveData();
//订阅消息
liveData.observe(this, new Observer>() {
@Override
public void onChanged(List beans) {
//数据接收
Toast.makeText(LiveDataActivity.this, "" + beans.get(0).getName(), Toast.LENGTH_SHORT).show();
}
});
发送消息代码
list.add(new Bean("张三"));
list.add(new Bean("李四"));
liveData.setValue(list);
使用很简单,那我们分析下liveData是源码时如何实现的呢?
liveData这么好,那么我们看看他的源码的核心逻辑
我们从获取ViewModel代码入口 ViewModelProviders.of(this).get(MyViewModel.class);
点击of()方法,代码很简单,获取activity的application,创建ViewModelProviders对象

点击get()方法,把ViewModel的实现类和类全类名,传给内部get方法

点击内部的get方法,代码很简单,先从一个ViewModelStore获取ViewModel,如果有就直接返回,没有就创建,再保存到ViewmodelStore,再返回。

我们看看工厂的create()方法是如何创建ViewModel的,看到下图源码就一目了然,使用反射创建的

我们看看ViewModelStore代码,就是个HashMap保存的ViewModel封装类,源码看多,有很多类似的使用map复用的类似代码。

现在我们看看MutablLiveData的setValue()方法,点击进去,没有什么代码,那应该调用父类的setValue方法,

点击到父类的setValue方法,调用了dispatchValue方法

我们看看dispatchValue做了些什么,又调用了considerNotify()方法,在这个方法最后行代码,他实现了接口Observer的onChanged()方法

最终还是通过接口回调方式,把数据给到订阅者。
这是有人问,那liveData是如何感知感知什么周期的呢?我们点击liveData的obser方法,会发现是使用Lifecycle实现生命周期的监听。

liveData源码介绍到这,下面是我们基于liveData封装的一个库,可以实现一行代码发送消息,一行代码订阅消息,还能感知生命周期,从数据根源上防止内存泄漏。
https://blog.csdn.net/qq_36237165/article/details/104878044
喜欢的点星Thanks♪(・ω・)ノ
网友评论