2025-12-18 11:14:02 世界杯小组积分

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 list = new ArrayList<>();

@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 beans) {

//数据接收

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 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 MutableLiveData with(String key, Class t) {

//原理就是通过map管理key 和livedata ;key和livedata一一对应,

//先判断map 中是否包含传进来的key对应的值(liveData),有就直接返回liveData,

没有就就创建个liveData保存到map里面

if (!map.containsKey(key)) {

map.put(key, new MutableLiveData());

}

return (MutableLiveData) map.get(key);

}

}

在activity使用liveDataBus

public class LiveDataActivity extends AppCompatActivity {

private MutableLiveData> liveData;

private List list = new ArrayList<>();

@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