LiveData 和 ViewModel 是 Google 官方的 MVVM 架构的一个组成部分。巧了,昨天分析了一个问题是 ViewModel 的生命周期导致的。今天又遇到了一个问题是 LiveData 通知导致的。而 ViewModel 的生命周期和 LiveData 的通知机制是它们的主要责任。所以,就这个机会我们也来分析一下 LiveData 通知的实现过程。
- 关于 ViewModel 的生命周期:《浅谈 LiveData 的通知机制》;
- 关于 MVVM 设计模式的基本应用,你可以参考这篇文章:《Android 架构设计:MVC、MVP、MVVM和组件化》.
1、一个 LiveData 的问题
今天所遇到的问题是这样的,
有两个页面 A 和 B,A 是一个 Fragment ,是一个列表的展示页;B 是其他的页面。首先,A 会更新页面,并且为了防止连续更新,再每次更新之前需要检查一个布尔值,只有为 false 的时候才允许从网络加载数据。每次加载数据之前会将该布尔值置为 true,拿到了结果之后置为 false. 这里拿到的结果是借助 LiveData 来通知给页面进行更新的。
现在,A 打开了 B,B 中对列表中的数据进行了更新,然后发了一条类似于广播的消息。此时,A 接收了消息并进行数据加载。过了一段时间,B 准备退出,再退出的时候又对列表中的项目进行了更新,所以此时又发出了一条消息。
B 关闭了,我们回到了 A 页面。但是,此时,我们发现 A 页面中的数据只包含了第一次的数据更新,第二次的数据更新没有体现在列表中。
用代码来描述的话大致是下面这样,
// 类 A
public class A extends Fragment {
private boolean loading = false;
private MyViewModel vm;
// ......
/**
* Register load observer.
*/
public void registerObservers() {
vm.getData().observe(this, resources -> {
loading = false;
// ... show in list
})
}
/**
* Load data from server.
*/
public void loadData() {
if (loading) return;
loading = true;
vm.load();
}
/**
* On receive message.
*/
public void onReceive() {
loadData();
}
}
public class B extends Activity {
public void doBusiness1() {
sendMessage(MSG); // Send message when on foreground.
}
@Override
public void onBackpressed() {
// ....
sendMessage(MSG); // Send message when back
}
}
public class MyViewModel extends ViewModel {
private MutableLiveData<Resoucres<Object>> data;
public MutableLiveData<Resoucres<Object>> getData() {
if (data == null) {
data = new MutableLiveData<>