Jetpack篇——LiveData源码分析

一、分析内容

Jetpack 中,LiveData 的源码是最简单的,整个 core 只包含 3 个文件,而且主类 LiveData 也不超过 500 行的代码,但其重要性却不言而喻……

对于 LiveData 的源码,我们需要分析的有以下几个地方:

  1. 其生命周期的管理
  2. 值的传递(setValue和postValue)
  3. setValue和postValue的区别

二、生命周期的管理

在使用 LiveData 的时候有一行重要的代码:

/**
 *  在某个 Activity 中
 */
liveData.observe(this, Observer {
    
    
	Log.e("==>",it.toString())
})

我们可以看看 LiveData.observe(LifecycleOwner owner, @NonNull Observer<? super T> observer) 这个方法,第一个参数是 LifecycleOwner,这是个接口,其意义是使得一个类拥有 生命周期 的能力,翻开 Activity 的继承关系,在 ComponentActivity 的时候,就继承了该接口,那么如果我们的 Activity 是继承于 ComponentActivity 往后的 Activity ,都可以将 this 传入observe() 的第一个参数中。

这一段是属于 Lifecycle 的源码,所以我们观看 LiveData 的源码时,务必要将其带入。直接看 LiveData.observe() 的源码:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    
    
    assertMainThread("observe");	//1
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
    
    	//2
        // ignore
        return;
    }
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);	//3
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);	//4
    if (existing != null && !existing.isAttachedTo(owner)) {
    
    	//5
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
    
    	//6
        return;
    }
    owner.getLifecycle().addObserver(wrapper);	//7
}

我们首先就看到 @MainThread 的注解,这就说明该方法必须是在主线程中调用。

  1. 这行代码就是验证该线程是否在主线程,如果不在主线程中,那么就会直接抛出异常提醒可爱的程序员们。
  2. 通过 LifecycleOwner 拿到其生命周期,在获取生命周期现在的状态,如果现在的状态是 DESTROYED 销毁的时候,那么就不必废话,直接 return
  3. 这里出现了一个 LiveData 的内部类:LifecycleBoundObserver,这个类继承于另一个内部抽象类: ObserverWrapper,看名字是个包装类,用于封装一些东西的操作。再看看 LifecycleBoundObserver 还继承了 LifecycleEventObserver 接口,所以我们直接看到 标记 7 的代码, 进行了生命周期的注册。所以当 Activity 的生命周期发生变化的时候,那么 LifecycleBoundObserver 就能够收到变化的监听,那么该类会进行哪些操作呢?直接看代码:
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {
    
    
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
    
    
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());	
    }

当当前的生命周期的状态是 DESTROYED 的时候,啊么就会移除 Observer,这个 Observer 就是 标记 4 添加进入的。

  1. mObservers 是一个 SafeIterableMap 类型的集合,这并不是一个 Map,这是个 LinkedList,只不过是以键值对的形式来模拟 Map 的功能。其调用了 putIfAbsent 方法,如果该 Key 已经对应了一个 Value,那么就把旧的 Value 拿出来,把新的 Value 赋值上去……
  2. 这里会把旧的 Value 进行一步判断,如果旧的 Value 没有绑定了 LifecycleOwner 就会抛出异常。这意思不是很明显了,其触发的条件不太好理解,所以我们直接看异常的信息:不能将同一个 observer 绑定不同的生命周期。这里有个小例子会触发异常:
/**
 *  某 Fragment 中
 */
val observer = Observer<Boolean>{
    
    
	Log.e("==>",it.toString())
}

liveData.observe(activity!!,observer)
liveData.observe(viewLifecycleOwner,observer)
  1. 如果通过 标记 5 的代码,那么这行代码的作用就是避免多次的生命周期管理,其发生的场景为:
/**
 *  某 Fragment 或 Activity 中
 */
val observer = Observer<Boolean>{
    
    
	Log.e("==>",it.toString())
}

liveData.observe(this,observer)
liveData.observe(this,observer)	//通过,无异常
  1. 注册生命周期的监听。

小结:通过 LiveData.observer() 来进行生命周期管理的注册,此时已经形成 LiveData 和传入的 LifecycleOwner 的生命周期绑定。在生命周期的状态变成 DESTROYED 的时候,会自动的解除绑定。

三、值的传递

LiveData 值的传递有两种情况,第一种情况就是初始化的情况:
private val liveData = MutableLiveData<Boolean>(true),即在 LiveData 被初始化的时候,就已经赋值了。

第二种情况就是通过:liveDta.setValue()liveDta.postValue() 进行值的传递。

下面我们逐一分析。

1、初始化的值

直接看其构造方法:

private volatile Object mData;
static final int START_VERSION = -1;

public LiveData(T value) {
    
    
    mData = value;
    mVersion = START_VERSION + 1;
}

从这里我们就可以知道一些信息了:

  1. LiveData 的值会被保存至一个拥有原子性的 mData 对象中。
  2. 赋值时 START_VERSION 会加 1,版本号加 1 预示着值发生变化。

我们看到这个构造方法中并没有出现 xxxDispatchData()、onNewValue() 等方法来通知 Observer 有值的传递,那么这个值是怎么传到 Observer 中的呢?

那当然是借助生命周期了

我们回到 LifecycleBoundObserver 这个类的 onStateChanged() 方法中,每当生命周期发生变化时,都会调用该方法:

@Override
public void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {
    
    
    if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
    
    	//1
        removeObserver(mObserver);
        return;
    }
    activeStateChanged(shouldBeActive());	//2
}

前面的代码我们已经分析过了,这是当生命周期的状态是销毁时,就会解除 Observer 对于 LiveData 的监听。假设此时的生命周期从 ONSTART 到 ONRESUME。

那么看一下下面的代码 activeStateChanged(shouldBeActive())

@Override
boolean shouldBeActive() {
    
    	//1
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

void activeStateChanged(boolean newActive) {
    
    
    if (newActive == mActive) {
    
    	//2
        return;
    }
    mActive = newActive;	//3
    boolean wasInactive = LiveData.this.mActiveCount == 0;	//4
    LiveData.this.mActiveCount += mActive ? 1 : -1;	//5
    
    ... ...//省略不相关代码
    
    if (mActive) {
    
    	//6
        dispatchingValue(this);
    }
}
  1. shouldBeActive() 是来检测当前的 生命周期是否是在 STARTED 之后,如果是的话,就返回 true,代表此时的生命周期是激活的状态。
  2. 当此时的生命周期来到 RESUMEshouldBeActive() 返回的是 true,即 newActive == true,而 mActiveboolean 类型,默认值为 false,所以此时的 newActive == mActive 一定是 fasle
  3. 然后更新 mActive,表示现在是生命周期激活的时候。
  4. LiveData.this.mActiveCount 是个int 类型,并且初始值为 0,那么这行代码的意思就是判断 LiveData 此时是否为激活的状态,很显然这次是 true,为不活跃的状态。
  5. 当现在是激活的状态,那么将 LiveData.this.mActiveCount 加 1。
  6. 如果现在是激活的状态那么就执行 dispatchingValue(this),看这个方法的名字就觉得这肯定是将 value传给 Observer

接下来的重点就是 dispatchingValue() 这个方法了:

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    
    
    if (mDispatchingValue) {
    
    	//1
        mDispatchInvalidated = true;	//1.1
        return;
    }
    mDispatchingValue = true;	//2
    do {
    
    						//3
        mDispatchInvalidated = false;
        if (initiator != null) {
    
    
            considerNotify(initiator);	//4
            initiator = null;
        } else {
    
    
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    
    
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
    
    
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

首先看这个方法唯一参数的名称:initiator,译为发起人。

  1. mDispatchingValueboolean 类型,初始值为 false,所以直接往下走。
  2. mDispatchingValue 赋值为 true
  3. 此时来到一个do while() 的循环,我们先看 while() 中的表达式,只是一个 boolean 类型的 mDispatchInvalidated,所以这个值第一次默认为 false那么我们现在就可以肯定这个 do while() 的循环只执行一次。但是我们纵观全局,mDispatchInvalidated = true 只存在 标记 1.1 的代码中,所以这个 do while() 的循环条件就是:dispatchingValue() 被多次调用。
  4. 因为我们有传值过来,所以我们走 标记 4 的分支。直接看方法 considerNotify() 的代码:
private void considerNotify(ObserverWrapper observer) {
    
    
    if (!observer.mActive) {
    
    	//5
        return;
    }
    if (!observer.shouldBeActive()) {
    
    	//6
        observer.activeStateChanged(false);
        return;
    }
    if (observer.mLastVersion >= mVersion) {
    
    	//7
        return;
    }
    observer.mLastVersion = mVersion;	//8
    observer.mObserver.onChanged((T) mData);	//9
}
  1. 通过之前的分析,我们知道此时的 mActive 是为 true 的。
  2. shouldBeActive() 这个方法我们前面也分析过,返回当前的生命周期是否在 STARTED 之后,很明显现在返回的也是 true
  3. 判断上次的 version 和现在的 version 值,如果上次的 version 大于或等于现在的 version,那么就直接 return ,放弃执行后面的代码。observer.mLastVersion 初始值就是 -1,而 mVersion 在最开始 LiveData 的构造函数中被增加了 1,现在的值为 0 ,所以此时的 observer.mLastVersion 肯定是小于 mVersion 的。
  4. 更新 observer.mLastVersion
  5. 拿到 Observer ,并且调用 onChanged 方法,终于到最后看到了回调。

小结:LiveData 初始化的值,会依赖于生命周期的回调,进行值得更新。

2、setValue 和 postValue

我们直接分析 setValue,不着急分析 postValue

@MainThread
protected void setValue(T value) {
    
    
    assertMainThread("setValue");	//1
    mVersion++;	//2
    mData = value;	//3
    dispatchingValue(null);	//4
}

这也是个被 @MainThread 标注的方法,说明该方法只能在主线程中调用。

  1. 判断当前线程是否是主线程。
  2. mVersion 加 1。
  3. 赋值新的值。
  4. 开始分发值了,这一步我们可以回到上面的源码分析,只不过此时该方法传递的值为 null,所以我们走的就是另一条分支了:
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    
    
    considerNotify(iterator.next().getValue());
    if (mDispatchInvalidated) {
    
    
        break;
    }
}

这一步就是遍历所有的 Observer,然后再通过 considerNotify() 方法进行分发。这个方法上面已经分析过了,所以 setValue() 的内容就是这么多……

西瓜
那么 postValue 呢?看下一小节吧。

四、setValue和postValue的区别

请移步:LiveData setValue和postValue的区别及详解

五、总结

LiveData 的源码是比较简单的,整体框架基于 观察者模式,其亮点就在于和生命周期的绑定,使得我们不必要手动的调用 unRegister() 之类的代码。

在整个 Jetpack 的体系中,LiveData 扮演者很重要的角色,其利用价值就是使得数据安全的跨线程传递。

猜你喜欢

转载自blog.csdn.net/catzifeng/article/details/107298286