liveData使用和封装一个liveDataBus消息总线和源码分析
今天介绍jetpack的liveData使用,有些人可能会问,liveData是什么,你可以把它理解可以感知生命的容器,当一个类被销毁,是接收不到这个容器的数据的。是不是感觉很神奇。这样数据导致的内存泄漏问题就可以从根本上解决了。
------------------------使用篇-------------------------
//在build导依赖包
//使用liveData
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
//创建个类继承ViewModel;创建个方法获取mutablLiveData(这个类是liveData的子类)
(如果是其他页面改变数据 建议 定义的mutableLiveData 必须被static修饰 ,要不系统获取不到报错)
/**
* liveData是个抽象类 ,可以理解为一个能感知生命周期的仓库
* mutableLIveData 是他的实现类
*/
public class MyViewModel extends ViewModel {
//注意使用static修饰 源码直接通过类获取
private static MutableLiveData> mutableLiveData;
//获取仓库
public MutableLiveData> getLiveData() {
if (mutableLiveData == null) {
mutableLiveData = new MutableLiveData<>();
}
return mutableLiveData;
}
}
//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;
}
}
//在activity通过系统API的ViewModelProviders获取刚创建的MyViewModel类,再获取MutablLiveData对象,在需要接收数据的地方调用obser方法,在onChanged方法获取数据。
//通过往liveData添加数据,实现数据的发送。
public class LiveDataActivity extends AppCompatActivity {
private MutableLiveData> liveData;
private List
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_data);
/**
* 正常使用liveData
*/
//调用系统API获取 viewModel
MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
liveData = myViewModel.getLiveData();
//订阅消息
liveData.observe(this, new Observer>() {
@Override
public void onChanged(List
//数据接收
Toast.makeText(LiveDataActivity.this, "" + beans.get(0).getName(), Toast.LENGTH_SHORT).show();
}
});
}
/**
* 正常使用liveData 发送数据
*/
public void load(View view) {
//添加数据到liveData仓库(发送消息)
list.add(new Bean("张三"));
list.add(new Bean("李四"));
liveData.setValue(list);
}
}
-------------------------封装LIveDataBUS----------------
//下面我们封装个LiveDataBus,可以实现EventBus所有功能,而且还可以区分订阅者,重点不会导致内存泄漏。
//封装思路很简单,就是用个map,key作为数据区分的tag,以MutableLiveData为容器装载数据,就这么简单,
public class LiveDataBus {
private Map
//双重校验锁 单利
private static volatile LiveDataBus liveDataBus;
private LiveDataBus() {
//初始化map
map = new HashMap<>();
}
public static LiveDataBus getInstance() {
if (liveDataBus == null) {
synchronized (LiveDataBus.class) {
if (liveDataBus == null) {
liveDataBus = new LiveDataBus();
}
}
}
return liveDataBus;
}
//封装liveData
public synchronized
//原理就是通过map管理key 和livedata ;key和livedata一一对应,
//先判断map 中是否包含传进来的key对应的值(liveData),有就直接返回liveData,
没有就就创建个liveData保存到map里面
if (!map.containsKey(key)) {
map.put(key, new MutableLiveData
}
return (MutableLiveData
}
}
在activity使用liveDataBus
public class LiveDataActivity extends AppCompatActivity {
private MutableLiveData> liveData;
private List
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live_data);
/**
* 使用封装的liveData
*/
LiveDataBus.getInstance().with("1", Bean.class).observe(this, new Observer
@Override
public void onChanged(Bean bean) {
Toast.makeText(LiveDataActivity.this, "" + bean.getName(), Toast.LENGTH_SHORT).show();
}
});
}
/**
* 使用封装的liveData 发送数据
*/
public void send(View view) {
Bean bean = new Bean("测试");
LiveDataBus.getInstance().with("1", Bean.class).setValue(bean);
}
}
//总结使用封装的总线,只能发送bean数据,如果你的数据是集合什么的需要封装到bean里面。其他跟Evnetbus一样。如果你想使用原生的也可以。
----------------------------------源码分析篇-------------------------------------------
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实现生命周期的监听。
//如果对Lifecycle不了解的可以看我这篇文章
https://blog.csdn.net/qq_36237165/article/details/102544785
//当我们旋转屏幕,发现使用liveData时,数据没有丢失,这是如何实现的呢。以前调用onSaveInstancestate()保存数据,调用onRestoreInstanceState()恢复数据。当我看livedata源码发现viewModelStroe保存在ComponentActivity的NonConfigurationInstances的静态类部类,也就是说livedata是跟app的生命周期一致的,activity被销毁对他没有影响。
//源码地址:https://github.com/zhudaihao/jetpack