掘金文章链接
基于:
macOs:10.14/AS:3.4/Android build-tools:28.0.0
思路
看源码前先考虑下如果要自己实现 LiveData
应该怎么做?
基本做法:
- 目标数据私有;
- 开放
setter
方法用于更新目标数据; - 提供方法添加数据变化监听器(
Observer
);
扩展:
- 允许子线程更新数据, 因此
setter
需要考虑同步; - 项目中可能多个地方需要用到目标数据,因此回调监听器(
Observer
)需支持添加多个; - 遍历通知各
Observer
更新数据期间若数据发生了变化,要如何处理; - 数据变化时常常都需要更新UI,而UI有生命周期,因此
Observer
需要提供Lifecycle
相关逻辑支持,包括:- 定义处于哪些生命周期的
Observer
可以收到数据更新; -
onDestroy()
时自动移除Observer
等;
- 定义处于哪些生命周期的
- 如何定义
数据变化
呢? 最简单直接的做法是每次触发setter
方法时都当作数据发生了变化, 遍历通知所有Observer
即可, 更进一步的判定交给调用方;
......
简单使用
// 定义 livedata
object ParaConfig {
// 定义一个私有的 `MutableLiveData`
private val msgLiveData = MutableLiveData()
// 开放给外部获取数据更新时,提供不可变的 `LiveData` 即可;
fun getMsgLiveData(): LiveData = msgLiveData
fun updateMsg(msg: String, inBgThread: Boolean = false) {
if (inBgThread) {
msgLiveData.postValue(msg) // 在子线程中更新数据
} else {
msgLiveData.value = msg // 在主线程中更新数据
}
}
}
// 添加 `Observer`
class LiveDataFrag : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 添加一个跟生命周期相关的 `Observer`
ParaConfig.getMsgLiveData().observe(this, Observer { newMsg ->
tv_msg.text = newMsg
})
// 无视生命周期, 每次数据变化时都会回调,需要自行移除observer
ParaConfig.getMsgLiveData().observeForever {
Logger.d("observeForever: $it","tag_livedata")
}
}
}
看源码我还是习惯从调用入口一步步往下看, 以下也是按照这种顺序来;
实现
添加 Observer
// LiveData.java
public abstract class LiveData {
private static final Object NOT_SET = new Object();
// 实际数据,类型为 Object 而非 T
private volatile Object mData = NOT_SET;
// 存储所有的 Observer
private SafeIterableMap, ObserverWrapper> mObservers = new SafeIterableMap<>();
// 添加跟生命周期相关的 observer
// 目标数据
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
// 若 LifecycleOwner 已处于已被销毁,则忽略该 observer
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
// 将 LifecycleOwner 和 Observer 功能进行绑定包装
// 生成支持生命周期感知的 Observer: LifecycleBoundObserver
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 避免重复添加相同的observer
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
// 实现对 LifecycleOwner 生命周期的感知
// 关键还是 LifecycleBoundObserver 类,我们马上进去看一下
owner.getLifecycle().addObserver(wrapper);
}
// 无视生命周期, 每次数据发生变化时,都会回调通知 Observer
// 需要手动在不需要时移除 Observer
@MainThread
public void observeForever(@NonNull Observer observer) {
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
}
MutableLiveData
只是简单重写了 LiveData
的 setValue(T)
/postValue(T)
方法, 改为 public
而已;
数据如何传递的: setValue(T)
解析
// LiveData.java
@MainThread
protected void setValue(T value) {
// 只能在UI线程中调用,否则抛出异常,崩溃
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
private boolean mDispatchingValue;
// 若参数 initiator 非空,则表示只通知特定的 ObserverWrapper, 否则是回调通知所有 ObserverWrapper
// 由于只在主线程中调用,因此不用做多线程处理
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
// 小技巧: 在遍历通知各 ObserverWrapper 期间, 若数据发生了变化, 则会重新遍历通知
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {// initiator 非空时,只更新特定 ObserverWrapper
considerNotify(initiator); // 实际更新数据的方法
initiator = null;
} else { // 否则遍历更新所有 ObserverWrapper
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
// 若数据发生变化, 则退出for循环
// 而外层 do...while() 判定条件为true,就会重新遍历通知各 ObserverWrapper;
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
// 判断是否要将数据分发到指定的 ObserverWrapper
private void considerNotify(ObserverWrapper observer) {
// 是否可以分发数据到指定的 observer, 由 mActive 来控制
// 所以 mActive 很重要,具体下一节解读
if (!observer.mActive) {
return;
}
// 二次确认状态, 可能生命周期发生了变化,但 mActive 并未改变
if (!observer.shouldBeActive()) {
// active -> inactive 时通知更新状态
// inactive 状态下就不需要分发数据了
observer.activeStateChanged(false);
return;
}
// 若 ObserverWrapper 持有的数据值已是最新版本, 自然也不用分发
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
// 通知 observer 数据有更新
// observer.mObserver 是调用方实际传入的
observer.mObserver.onChanged((T) mData);
}
用于子线程调用的 postValue(T)
会发射一个 Runnable
到主线程中, 最终也是通过 setValue(T)
来实现数据分发;
当然, postValue(T)
也可以在主线程调用,不过是多此一举,如:
// observer会先收到 "msgFromSetValue" 然后才收到 "msgFromPostValue"
someBtnView.setOnClickListener {
msgLiveData.postValue("msgFromPostValue")
msgLiveData.value = "msgFromSetValue"
}
ObserverWrapper
类解析
// LiveData 的内部抽象类
// 包装用户传入的 Observer, 提供数据版本记录以及active状态(生命周期)判断
private abstract class ObserverWrapper {
final Observer mObserver;
boolean mActive; // 确定当前 ObserverWrapper 是否生效,true时才可进行数据更新
int mLastVersion = START_VERSION; // 当前持有的数据版本号,初始值为 -1
ObserverWrapper(Observer observer) {
mObserver = observer;
}
// 判断该 Observer 是否有效, true 时才会触发 activeStateChanged()
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
// 更新本 ObserverWrapper 的状态
void activeStateChanged(boolean newActive) {
// 若状态没变化,不需要更新,直接返回
if (newActive == mActive) {
return;
}
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
// 处于 active 状态的 observer 数量从0 -> 1时,触发 onActive() 方法
if (wasInactive && mActive) {
onActive();
}
// 处于 active 状态的 observer 数量从 1 -> 0时,触发 onInactive() 方法
// 提供给观察者释放资源的机会
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
// observer 从 inactive -> active 时, 更新数据
if (mActive) {
// 将数据发送给该 observer
dispatchingValue(this);
}
}
}
此类并未给出 inactive/active 具体是何种状态, 具体应是由 shouldBeActive()
来确定, 因此需要从子类查找;
子类 AlwaysActiveObserver
比较简单, 只是将shouldBeActive()
固定返回 true
,表示一直生效, 每次数据发生变化时都需要发送通知;
我们看下 LifecycleBoundObserver
类;
LifecycleBoundObserver
解析
// LiveData 内部类
// 将 LifecycleObserver 和 ObserverWrapper 结合,当生命周期变化时,通知 ObserverWrapper 更新数据
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
// 此处定义了哪些生命周期是 `active` 的
// 结合 Lifecycle.State 类 ,我们知道是: STARTED/RESUMED 两种状态
// 对应于生命周期 `onStart()` 之后到 `onStop()` 之前
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
// 生命周期变化时回调本方法
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
// 若当前 LifecycleOwner onDestory() 了, 则自动移除 observer, 避免内存泄露
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
// 将 shouldBeActive() 返回的状态当做本 ObserverWrapper 的状态
// 即 mActive = shouldBeActive()
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
小结
- 只能在主线程中进行
Observer
的添加:observe(@NonNull LifecycleOwner owner, @NonNull Observer
observer) observeForever(@NonNull Observer
observer)
- 添加带
LifecycleOwner
的Observer
时, 若发生onDestory()
,则会自动移除Observer
; - 数据只会在
LifecycleOwner
处于onStart()
/onResume()
/onPause()
生命周期时,才会分发; - 若处于 active 的
Observer
数量从 1 -> 0, 回调onInactive()
,适用于子类进行资源释放; - 若处于 active 的
Observer
数量从 0 -> 1, 回调onActive()
; -
LiveData
类和ObserverWrapper
类都会在内部持有一个数据版本号; -
LiveData
数据发生变化时,会切换到主线程,然后遍历所有Observer
, 并将数据分发给处于 active 状态并且数据版本号不一致的Observer
;