LiveData的定义

LiveData是一个可观察数据的持有者, 但是不像普通的可观察数据, LiveData绑定了生命周期,例如Activity, Fragment的生命周期。有点抽象, 还是先了解一下关键的类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Observer是一个接口,观察者。当数据改变时就回调onChanged
public interface Observer<T> {
void onChanged(@Nullable T t);
}

//LiveData类是个抽象类,这里先看看有什么暴露出去的方法
public abstract class LiveData<T> {
//添加观察者观察, 传入LifecycleOwner,用于来绑定生命周期
public void observe(LifecycleOwner owner, Observer<T> observer)
//添加观察者观察, 但是是没有LifecycleOwner
public void observeForever(Observer<T> observer)
//移除观察者
public void removeObserver(Observer<T> observer)
//移除某个LifecycleOwner里所有的观察者
public void removeObservers(final LifecycleOwner owner)
//是否有观察者
public boolean hasObservers()
//是否有活的观察者
public boolean hasActiveObservers()
}
//MutableLiveData继承LiveData, 多开放2个方法。
public class MutableLiveData<T> extends LiveData<T> {
public void postValue(T value) //post一个数据
public void setValue(T value) //设置一个数据
//postValue和setValue的区别是:post可以在子线程用,而setValue只能在UI线程调用
}

介绍完了主要的类,下面举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 这段代码通常在Activity或者Fragment中, 用liveData去添加一个观察者
// AppCompatActivity或者Fragment已经LifecycleOwner,通常传this即可
// 当User数据有变化时,onChanged方法会被调用, 用于更新UI
liveData.observe(this, new Observer<User>() {
@Override
public void onChanged(@Nullable User user) {
//更新UI
}
});

//下面这段代码通常在ViewModel中,这里liveData和上面代码的liveData是同一个
//可以通过postValue或者setValue去改成user数据, 有数据改变时, onChanged方法会被回调
//假如一个场景, 在ViewModel中,通过网络请求去拿user数据,然后postValue就会去通知UI层onChanged去更新UI
//liveData大概就是这个流程
liveData = new MutableLiveData<User>()
liveData.postValue(user)// 或者setValue(user)

下面还是看看LiveData源码去了解一下原理

工作原理

这里以observe(LifecycleOwner owner, Observer observer) 和 postValue之间数据的通讯为例分析。下面看LiveData.observe源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
//判断当前生命周期是DESTROYED, 立马return, 都销毁了,添加观察者没意义
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}


LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//LifecycleBoundObserver继承ObserverWrapper, LifecycleBoundObserver实现LifecycleOwner
//mObservers这是一个Map, key是observer, value是ObserverWrapper
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//添加生命周期的观察者
owner.getLifecycle().addObserver(wrapper);
}

接着看LifecycleBoundObserver和ObserverWrapper片段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;

@Override
boolean shouldBeActive() {
//至少是STARTED状态
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

//GenericLifecycleObserver继承自LifecycleObserver, 当生命周期改变时onStateChanged会被回调
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//生命周期处于DESTROYED时, 移除观察者,mObserver是livedata.observe时传进来
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
//shouldBeActive()方法实现在当前类, 调用isAtLeast(STARTED), 至少是STARTED状态才是true
//就是生命周期在STARTED和RESUME状态时, 才是true
//接着调用了父类的activeStateChanged
activeStateChanged(shouldBeActive());
}
}

private abstract class ObserverWrapper {

void activeStateChanged(boolean newActive) {
// mActive状态相同立即返回
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
//就是生命周期在STARTED和RESUME时, mActive为true, 其他为false
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
//当mActive=true时, mActiveCount会加1, 当mActive=false时, mActiveCount会减1。
//这里为什么要加1和减1呢,结合Activity生命周期去考虑,当Activity.onCreate -> Activity.onStart -> Activity.onResume, State由CREATED->STARTED->RESUMED,这个过程当到STARTED时mActive为true,mActiveCount加1后为1, 接着RESUMED, mActive还是true, 这方法第一句(newActive == mActive)条件成立直接return, mActiveCount此时还是1。
//当Activity.onResume->Activity.onPause->Activity.onStop,State由RESUMED->STARTED->CREATED, Activity.onStop后State为CREATED, isAtLeast(STARTED)就为false, 此时mActive=false, mActiveCount减1,mActiveCount为0啦。
//当Activity.onStop->Activity.onStart->Activity.onResume, State由CREATED->STARTED->RESUMED, mActive为true,mActiveCount加1后为1, mActiveCount此时为1。
if (wasInactive && mActive) {
//根据上面一大段分析后,onActive会在Activity首次显示UI调用,从后台返回或者从另一个Activity回退后又调用一次。(打开透明Activity不走onStop,这种情况除外)
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
// Activity.onStop后调用
onInactive();
}
if (mActive) {
//分发数据, 跟踪dispatchingValue方法,会到LiveData.considerNotify方法
dispatchingValue(this);
}
}
}

private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
//mActive可以知道是否处于onStop状态, 是Stop状态就不要分发数据
return;
}
if (!observer.shouldBeActive()) {
//shouldBeActive()再次检查是否observer活着
//ObserverWrapper的实现类不止LifecycleBoundObserver, 这里暂时没看懂为什么再次检查
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
//mVersion会在调用postValue()或者setValue()处+1
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
调用onChanged分发改变的数据
}

接着看postValue方法是是如果把值传到onChanged里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
 
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
// 一开始看到这里有点疑问,1. 为什么加锁, 1. 为什么要一个NOT_SET变量(NOT_SET是一个Obj对象)
// 先带着疑问往下看
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) { // 先往下看,和加锁问题一起解释
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
// mPostValueRunnable运行在主线程
}

private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) { //加锁, 和postValue里的锁是一样的
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};

@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++; // 版本号加1,保证mVersion>mLastVersion
mData = value; // 赋值给mData, 数据会分发到mObserver.onChanged
dispatchingValue(null);

//到这里很清晰啦,现在回头看看postValue和mPostValueRunnable里的锁,和NOT_SET的作用
//1. postValue方法可能会被很多条线程调用
//2. mPostValueRunnable异步运行在主线程, 主线程是串联执行的,一次执行一个runnable
//3. 不加锁很明显不行, 多线程调用时, value从postValue方法赋值给mPendingData,
//在mPostValueRunnable主线程里把mPendingData赋值给mData,
//mPendingData和mData都是指向同一个对象, mData在主线程都是指向了最新的对象。
//在主线程队列的里mPostValueRunnable每次运行都是拿了最新的数据,有点多余
//4. 假如去掉NOT_SET, value从postValue方法赋值给mPendingData,
// 再到setValue的mData, mPendingData和mData都是指向同一个对象,
// 虽然加了锁也没用。但有了NOT_SET就不同啦, mPendingData地址给mData,NOT_SET地址给mPendingData,
// 在postValue方法的子线程里新进来的value地址又赋值给mPendingData。
//5.看回postValue方法里 if (!postTask) { return } 这个地方,
// 假如A线程调用了postValue, 把value赋值给mPendingData并释放了锁,
// 把A.mPostValueRunnable放到主线程的Message中,
// 但这时之前的B.mPostValueRunnable还没运行完,运行到setValue方法,也没有持有锁。
// 这时B线程也调用了postValue, 这时A.mPostValueRunnable还没运行,没有把mPendingData=NOT_SET,
// B线程postTask就为false了, 接着又把value赋值给mPendingData, 接着就直接return。
// 等A.mPostValueRunnable运行时, mPendingData又被B线程更新啦。
// if (!postTask) { return } 这个判断能减少主线程没必要mPostValueRunnable运行,
// 而且能更新到最新的数据。

}

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
// initiator是null , 下面是遍历mObservers存储ObserverWrapper通知所有观察者
...
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
// considerNotify前面分析过了,看回LiveData.observe的过程, 最终分发数据Observer.onChanged
}
}

LiveData优点

  • UI和数据保持一致:遵循观察者模式,生命周期状态更改时,LiveData会通知Observer对象
  • 避免内存泄漏:观察者绑定到Lifecycle对象,并在其相关生命周期走向Destroy后自行清理
  • 不会因stop而崩溃:处于非活动状态,不会接收到LiveData事件,如Activity变为不可见
  • 自动感知生命周期:LiveData自动管理在观察时意识到相关的生命周期状态变化。
  • 数据始终保持最新:生命周期变为非活动状态再次变为活动状态时接收最新数据。 例如,Activity不可见变为可见时立即接收最新数据
  • 解决Configuration changes问题:当屏幕旋转或者回收时,重新创建Activity或Fragment,可以即时收到数据变更
  • 共享资源:使用单例扩展LiveData,就可在app中共享它