LiveData
是Android Architecture Components
其中的一个组件。主要用于更新UI数据和组件之间传值。
1、LiveData是一种持有可被观察数据的类。它通过观察者模式实现了数据变化的动态通知,即当观察者生命周期处于活跃状态时,能够感知数据的变化。
2、能够感知生命周期,内部通过Lifecycle来感知生命周期,在Activity、Fragment、Service中当对应生命周期为Destroy的时候,会销毁观察者,避免内存泄露;
LiveData的使用十分方便,只需要简单的三步:
1、创建LiveData对象,LiveData
是抽象类,所以需要创建它的子类MutableLiveData
;
2、设置观察者observe,第一个参数是LifecycleOwner
对象,第二个是观察者监听,当数据改变的时候会在onChanged
方法内做出响应;
3、设置数据,通过postValue
或者setValue
方法来更新数据;
public class MainActivity extends AppCompatActivity {
private MutableLiveData liveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1.创建LiveData对象
liveData = new MutableLiveData();
// 2.添加观察者
liveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
// 提示数据变化
Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show();
}
});
findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 3.改变数据
liveData.postValue("测试");
}
});
}
}
一、LiveData是如何实现观察者订阅,并发送事件的?
LiveData通过observe和observeForever来订阅观察者,查看源码可以看到
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
///1、判断当前状态是否是DESTROYED,如果不是则添加观察者
if (owner.getLifecycle().getCurrentState() != State.DESTROYED) {
///2、创建LifecycleBoundObserver类
LiveData<T>.LifecycleBoundObserver wrapper = new LiveData.LifecycleBoundObserver(owner, observer);
///3、将观察者和LifecycleOwner添加到map中一一对应
LiveData<T>.ObserverWrapper existing = (LiveData.ObserverWrapper)this.mObservers.putIfAbsent(observer, wrapper);
// 对应观察者只能与一个owner绑定
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer with different lifecycles");
} else if (existing == null) {
// 当不存在的时候添加LifecycleObserver
owner.getLifecycle().addObserver(wrapper);
}
}
}
1、源码首先判断当前状态是否是DESTROYED
,如果不是则不会注册当前;
2、创建LifecycleBoundObserver
类,该类实现了生命周期与观察者的绑定,在此类中有个onStateChanged方法如下,onStateChanged方法中会在生命周期状态发生改变时判断当前状态是否是DESTROYED,如果是就移除当前监听者,避免内存泄露。
public void onStateChanged(LifecycleOwner source, Event event) {
// 当生命周期处于DESTROYED的时候移除当前订阅者
if (this.mOwner.getLifecycle().getCurrentState() == State.DESTROYED) {
LiveData.this.removeObserver(this.mObserver);
} else {
// 非DESTROYED的时候进行状态改变
this.activeStateChanged(this.shouldBeActive());
}
}
LifecycleBoundObserver
类继承ObserverWrapper类,ObserverWrapper又是观察者的包装类。
LifecycleBoundObserver
类通过实现了GenericLifecycleObserver
接口->LifecycleEventObserver
接口,最终实现了LifecycleEventObserver
接口,所以下面将wrapper添加到Lifecycle
的监听中。
owner.getLifecycle().addObserver(wrapper);
3、LiveData中创建了一个Map来存储每一个观察者和生命周期的包装类,并且会判断当前对应观察者只能与一个owner绑定。
二、postValue和setValue过程分析
LiveData可以通过postValue和setValue来设置数据,当请求完网络数据的时候,就可以调用postValue或setValue来设置数据,当然postValue是可以在任意线程进行调用,setValue只能在主线程调用。postValue最终也是调用setValue方法。
下面分析一下postValue的源码执行过程:
MutableLiveData
类中的postValue和setValue都是调用了父类(LiveData)的方法。直接查看LiveData的postValue方法:
protected void postValue(T value) {
boolean postTask;
synchronized(this.mDataLock) {
postTask = this.mPendingData == NOT_SET;
this.mPendingData = value;
}
if (postTask) {
// 转到主线程去执行,所以postValue方法可以在任意线程执行
ArchTaskExecutor.getInstance().postToMainThread(this.mPostValueRunnable);
}
}
源码中最终会转到主线程去执行,所以postValue方法可以在任意线程执行,再查看mPostValueRunnable
源码:
public LiveData() {
this.mData = NOT_SET;
this.mPendingData = NOT_SET;
this.mVersion = -1;
this.mPostValueRunnable = new Runnable() {
public void run() {
Object newValue;
synchronized(LiveData.this.mDataLock) {
newValue = LiveData.this.mPendingData;
LiveData.this.mPendingData = LiveData.NOT_SET;
}
// 这里最终调用了setValue方法
LiveData.this.setValue(newValue);
}
};
}
在LiveData的构造方法中创建了mPostValueRunnable
,并在最后调用了setValue方法。下面再看一下setValue方法:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
// 版本+1
++this.mVersion;
// 将值赋值给全局变量mData
this.mData = value;
// 分发数据
this.dispatchingValue((LiveData.ObserverWrapper)null);
}
setValue中主要做了三个事:
1、版本+1,LiveData的mVersion变量表示的是发送数据的版本,每次发送一次数据, 它都会+1;
2、将值赋值给全局变量mData;
3、调用dispatchingValue
方法分发数据,dispatchingValue
方法中主要调用的是considerNotify
方法
private void considerNotify(LiveData<T>.ObserverWrapper observer) {
// 如果观察者处于活跃状态
if (observer.mActive) {
// 判断是否应该改变状态
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
} else if (observer.mLastVersion < this.mVersion) {// 当观察者的最后版本小于当前版本,表示有数据改变了
// 将当前版本跟观察者的版本进行统一
observer.mLastVersion = this.mVersion;
// 触发onChange方法
observer.mObserver.onChanged(this.mData);
}
}
}
查看shouldBeActive
方法,这里通过LifeCycle的当前状态对比State.STARTED来判断,当是STARTED或者RESUMED状态时,才会触发observer的activeStateChanged方法,这时就会执行LifecycleBoundObserver
中的activeStateChanged
方法。
boolean shouldBeActive() {
return this.mOwner.getLifecycle().getCurrentState().isAtLeast(State.STARTED);
}
另外,当observer的mLastVersion(初始值为-1)版本小于LiveData的mVersion时,就表示有新数据改变了,所以就会触发onChanged方法。
三、observe和observeForever区别
observer会自动监听生命周期,当是STARTED和RESUMED的时候才会触发订阅,而observeForever则是会一直检测数据变化,只要数据变化了就会触发订阅。
@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
assertMainThread("observeForever");
// 会创建一个总是活动的观察者
LiveData<T>.AlwaysActiveObserver wrapper = new LiveData.AlwaysActiveObserver(observer);
......
}
如源码所示,observeForever会创建一个总是活动的观察者AlwaysActiveObserver
,改类继承ObserverWrapper,并实现了shouldBeActive
方法,而且始终返回true,所以只要数据一改变,会触发onChanged
方法。
private class AlwaysActiveObserver extends LiveData<T>.ObserverWrapper {
AlwaysActiveObserver(Observer<? super T> observer) {
super(observer);
}
// 一直返回true
boolean shouldBeActive() {
return true;
}
}
而在LifecycleBoundObserver
中实现了onStateChanged
方法,在该方法中会根据当前状态是否为State.DESTROYED来自动移除监听者,所以observeForever则不会,所以需要在onDestroy中手动移除。
@Override
protected void onDestroy() {
super.onDestroy();
// 使用observeForever需要手动移除
liveData.removeObserver(MyObserver);
}
四、LiveData粘性事件和数据倒灌
粘性事件:先setValue/postValue,后调用observe(),如果成功收到了回调,即为粘性事件。
数据倒灌:先setValue/postValue,后调用observe(new Obs()),至此收到了回调。然后再第二次调用observe(new anotherObs()),如果还能收到第一次的回调,则为“数据倒灌”。
大家可以看一下这篇文章:
关于LiveData粘性事件所带来问题的解决方案
UnPeek-LiveData
LiveDataBus