概述
文章目录
- 一、分析内容
- 二、生命周期的管理
- 三、值的传递
- 1、初始化的值
- 2、setValue 和 postValue
- 四、setValue和postValue的区别
- 五、总结
一、分析内容
在 Jetpack 中,LiveData 的源码是最简单的,整个 core 只包含 3 个文件,而且主类 LiveData 也不超过 500 行的代码,但其重要性却不言而喻……
对于 LiveData 的源码,我们需要分析的有以下几个地方:
- 其生命周期的管理
- 值的传递(setValue和postValue)
- 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
的注解,这就说明该方法必须是在主线程中调用。
- 这行代码就是验证该线程是否在主线程,如果不在主线程中,那么就会直接抛出异常提醒可爱的程序员们。
- 通过
LifecycleOwner
拿到其生命周期,在获取生命周期现在的状态,如果现在的状态是DESTROYED
销毁的时候,那么就不必废话,直接return
。 - 这里出现了一个 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 添加进入的。
- mObservers 是一个 SafeIterableMap 类型的集合,这并不是一个 Map,这是个 LinkedList,只不过是以键值对的形式来模拟 Map 的功能。其调用了
putIfAbsent
方法,如果该 Key 已经对应了一个 Value,那么就把旧的 Value 拿出来,把新的 Value 赋值上去…… - 这里会把旧的 Value 进行一步判断,如果旧的 Value 没有绑定了 LifecycleOwner 就会抛出异常。这意思不是很明显了,其触发的条件不太好理解,所以我们直接看异常的信息:不能将同一个 observer 绑定不同的生命周期。这里有个小例子会触发异常:
/**
* 某 Fragment 中
*/
val observer = Observer<Boolean>{
Log.e("==>",it.toString())
}
liveData.observe(activity!!,observer)
liveData.observe(viewLifecycleOwner,observer)
- 如果通过 标记 5 的代码,那么这行代码的作用就是避免多次的生命周期管理,其发生的场景为:
/**
* 某 Fragment 或 Activity 中
*/
val observer = Observer<Boolean>{
Log.e("==>",it.toString())
}
liveData.observe(this,observer)
liveData.observe(this,observer) //通过,无异常
- 注册生命周期的监听。
小结:通过 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;
}
从这里我们就可以知道一些信息了:
- LiveData 的值会被保存至一个拥有原子性的 mData 对象中。
- 赋值时 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);
}
}
shouldBeActive()
是来检测当前的 生命周期是否是在 STARTED 之后,如果是的话,就返回 true,代表此时的生命周期是激活的状态。- 当此时的生命周期来到 RESUME,
shouldBeActive()
返回的是 true,即newActive == true
,而 mActive 是 boolean 类型,默认值为 false,所以此时的newActive == mActive
一定是 fasle。 - 然后更新 mActive,表示现在是生命周期激活的时候。
LiveData.this.mActiveCount
是个int 类型,并且初始值为 0,那么这行代码的意思就是判断 LiveData 之前是否为不激活的状态,很显然这次是 true,即之前是不活跃的状态。(这一段是为了激活 LiveData 的onActive
回调,在省略代码中,此处就不做研究)- 当现在是激活的状态,那么将
LiveData.this.mActiveCount
加 1。 - 如果现在是激活的状态那么就执行
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,译为发起人。
mDispatchingValue
是 boolean 类型,初始值为 false,所以直接往下走。- 将
mDispatchingValue
赋值为 true - 此时来到一个
do while()
的循环,我们先看while()
中的表达式,只是一个 boolean 类型的mDispatchInvalidated
,所以这个值第一次默认为 false,那么我们现在就可以肯定这个do while()
的循环只执行一次。但是我们纵观全局,mDispatchInvalidated = true
只存在 标记 1.1 的代码中,所以这个do while()
的循环条件就是:dispatchingValue() 被多次调用。 - 因为我们有传值过来,所以我们走 标记 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
}
- 通过之前的分析,我们知道此时的 mActive 是为 true 的。
shouldBeActive()
这个方法我们前面也分析过,返回当前的生命周期是否在 STARTED 之后,很明显现在返回的也是 true。- 判断上次的 version 和现在的 version 值,如果上次的 version 大于或等于现在的 version,那么就直接
return
,放弃执行后面的代码。observer.mLastVersion
初始值就是 -1,而mVersion
在最开始 LiveData 的构造函数中被增加了 1,现在的值为 0 ,所以此时的observer.mLastVersion
肯定是小于mVersion
的。 - 更新
observer.mLastVersion
- 拿到 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 标注的方法,说明该方法只能在主线程中调用。
- 判断当前线程是否是主线程。
- 将 mVersion 加 1。
- 赋值新的值。
- 开始分发值了,这一步我们可以回到上面的源码分析,只不过此时该方法传递的值为
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 扮演者很重要的角色,其利用价值就是使得数据安全的跨线程传递。
最后
以上就是妩媚冰淇淋为你收集整理的Jetpack篇——LiveData源码分析的全部内容,希望文章能够帮你解决Jetpack篇——LiveData源码分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复