美文网首页jetpack
LiveData源码解析

LiveData源码解析

作者: 冰川孤辰js | 来源:发表于2019-05-13 14:18 被阅读0次

    掘金文章链接

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

    思路

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

    基本做法:

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

    扩展:

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

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

    实现

    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 类解析

    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;

    相关文章

      网友评论

        本文标题:LiveData源码解析

        本文链接:https://www.haomeiwen.com/subject/thblaqtx.html