LiveData源码解析

基于: macOs:10.14/AS:3.4/Android build-tools:28.0.0

思路

看源码前先考虑下如果要自己实现 LiveData 应该怎么做?

基本做法:

  1. 目标数据私有;
  2. 开放 setter 方法用于更新目标数据;
  3. 提供方法添加数据变化监听器(Observer);

扩展:

  1. 允许子线程更新数据, 因此 setter 需要考虑同步;
  2. 项目中可能多个地方需要用到目标数据,因此回调监听器可以添加多个;
  3. 数据变化时常常都需要更新UI,而UI有生命周期,因此 Observer 需要提供 Lifecycle 相关逻辑支持,包括:
    1. 定义处于哪些生命周期的 Observer 可以收到数据更新;
    2. onDestroy() 时自动移除 Observer 等;
  4. 如何定义 数据变化 呢? 最简单直接的做法是每次触发 setter 方法时都当作数据发生了变化, 遍历通知所有 Observer 即可, 更进一步的判定交给调用方; ......

简单使用

// 定义 livedata
object ParaConfig {
    // 定义一个私有的 `MutableLiveData`
    private val msgLiveData = MutableLiveData<String>()

    // 开放给外部获取数据更新时,提供不可变的 `LiveData` 即可;
    fun getMsgLiveData(): LiveData<String> = 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<String> { newMsg ->
            tv_msg.text = newMsg
        })

        // 无视生命周期, 每次数据变化时都会回调,需要自行移除observer
        ParaConfig.getMsgLiveData().observeForever {
            Logger.d("observeForever: $it","tag_livedata")
        }
    }
}
复制代码

看源码我还是习惯从调用入口一步步往下看, 以下也是按照这种顺序来;

实现

添加 Observer

// LiveData.java
public abstract class LiveData<T> {
    private static final Object NOT_SET = new Object();
    // 实际数据,类型为 Object 而非 T
    private volatile Object mData = NOT_SET;
    // 存储所有的 Observer
    private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

    // 添加跟生命周期相关的 observer
    // 目标数据
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> 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<T> 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 只是简单重写了 LiveDatasetValue(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<Map.Entry<Observer<T>, 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<T> mObserver;
    boolean mActive; // 确定当前 ObserverWrapper 是否生效,true时才可进行数据更新
    int mLastVersion = START_VERSION; // 当前持有的数据版本号,初始值为 -1

    ObserverWrapper(Observer<T> 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<T> 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);
    }
}
复制代码

小结

  1. 只能在主线程中进行 Observer 的添加:
    1. observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer)
    2. observeForever(@NonNull Observer<T> observer)
  2. 添加带 LifecycleOwnerObserver 时, 若发生 onDestory() ,则会自动移除 Observer;
  3. 数据只会在 LifecycleOwner 处于 onStart()/onResume()/onPause() 生命周期时,才会分发;
  4. 若处于 active 的 Observer 数量从 1 -> 0, 回调 onInactive() ,适用于子类进行资源释放;
  5. 若处于 active 的 Observer 数量从 0 -> 1, 回调 onActive();
  6. LiveData 类和 ObserverWrapper 类都会在内部持有一个数据版本号;
  7. LiveData 数据发生变化时,会切换到主线程,然后遍历所有 Observer, 并将数据分发给处于 active 状态并且数据版本号不一致的 Observer;

转载于:https://juejin.im/post/5cd907166fb9a031ef63d66c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值