一文读懂LiveData 的粘性事件

作者: 愿天堂没Android | 来源:发表于2022-03-17 21:32 被阅读0次

    前言

    说的通俗一点,就是先发送数据,后订阅,也可以接收到数据。

    这其实本是livedata 的一个特性,但是却给我们的日常使用带来了非常的不便,而且不提供API来解除粘性事件,这种做法确实不是很友好。

    接下来,就带大家来揭秘一下LiveData 粘性事件的原理。

    前方大量源码来袭,如有不适者,可以直接跳总结。

    原理

    首先我们从发送消息开始

    liveData.postValue("页面1 发送的消息")
    
    

    发送消息有两个方法:setValue和postValue

    setValue 只能在主线程使用,postValue可以在任何线程使用,它被调用时,通过handler切换到主线程,再调用 setValue

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

    这里有个 mVersion 要注意一下,后面会用到。然后就是通过 dispatchingValue 方法来分发消息了。

        void dispatchingValue(@Nullable ObserverWrapper initiator) {
            if (mDispatchingValue) {
                mDispatchInvalidated = true;
                return;
            }
            mDispatchingValue = true;
            do {
                mDispatchInvalidated = false;
                if (initiator != null) {
                    considerNotify(initiator);
                    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;
        }
    
    

    在这个方法里,主要是参数传的观察者是否为空,如果不为空,则向此观察者分发消息,如果为空,将会从观察者集合里面遍历观察者,进行分发。在这里,我们主要看 considerNotify 方法。

        private void considerNotify(ObserverWrapper observer) {
            ...............
            if (observer.mLastVersion >= mVersion) {
                return;
            }
            observer.mLastVersion = mVersion;
            observer.mObserver.onChanged((T) mData);
        }
    
    

    在我们前面提到 mVersion 用到了这里,和 mLastVersion 做了比较,这点我们在下个步骤进行说明。

    这就是我们全部发送消息的过程了,很简单明了,但是还不足以窥全貌,接下来我们分析另外一个步骤,监听。

    liveData.observe(this) {
                Log.e("TAG", "onCreate: ")
                tv.setText("监听到的消息:$it")
            }
    
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            assertMainThread("observe");
            if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                // ignore
                return;
            }
            LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
            ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
            ............
            owner.getLifecycle().addObserver(wrapper);
        }
    
    

    在这里,主要是对我们的 ownerobserver 做了一层包装,然后让 lifecycle 进行了监听。然后我们就看看 包装了点什么

        class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
            @NonNull
            final LifecycleOwner mOwner;
    
            LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
                super(observer);
                mOwner = owner;
            }
           .........
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
                if (currentState == DESTROYED) {
                    removeObserver(mObserver);
                    return;
                }
                Lifecycle.State prevState = null;
                while (prevState != currentState) {
                    prevState = currentState;
                    activeStateChanged(shouldBeActive());
                    currentState = mOwner.getLifecycle().getCurrentState();
                }
            }
            ............
        }
    
    

    可以看到 LifecycleBoundObserver 继承了 ObserverWrapper ,实现了 LifecycleEventObserver 接口。

    LifecycleEventObserver 接口 主要是当 lifecycle 状态改变的时候会感应到,并进行回调。

    然后我们主要看看父类 ObserverWrapper

        private abstract class ObserverWrapper {
            final Observer<? super T> mObserver;
            boolean mActive;
            int mLastVersion = START_VERSION;
    
            ObserverWrapper(Observer<? super T> observer) {
                mObserver = observer;
            }
            ............
            void activeStateChanged(boolean newActive) {
                if (newActive == mActive) {
                    return;
                }
                // immediately set active state, so we'd never dispatch anything to inactive
                // owner
                mActive = newActive;
                changeActiveCounter(mActive ? 1 : -1);
                if (mActive) {
                    dispatchingValue(this);
                }
            }
        }
    
    

    是不是看到了一个熟悉的面孔,就是我们上个步骤 提到的 mLastVersion ,它是在这里定义的,并且默认是-1;这里会在后文进行贯穿起来,先了解它的源头。

    接下来,我们先继续走流程,还是LifecycleBoundObserver 类中,当状态改变的时候,会调用 onStateChanged 方法

      @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
                if (currentState == DESTROYED) {
                    removeObserver(mObserver);
                    return;
                }
                Lifecycle.State prevState = null;
                while (prevState != currentState) {
                    prevState = currentState;
                    activeStateChanged(shouldBeActive());
                    currentState = mOwner.getLifecycle().getCurrentState();
                }
            }
    
    

    当活跃状态改变的时候,会 调用 activeStateChanged :

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        mActive = newActive;
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            dispatchingValue(this);
        }
    }
    
    

    当状态是活跃状态的时候,会调用 dispatchingValue 进行数据分发,我们上文用到的分发是遍历所有观察者进行数据分发,这次是只分发当前观察者。

    总结

    接下来我们进行连贯一下:

    首先发送数据 postValue ,次数会让进行 mVersion++ 操作,然后遍历观察者进行分发。

    然后是进行监听操作,在进行监听的时候,会使用LifecycleBoundObserver 对观察者进行包装一下,在这个操作里面,LifecycleBoundObserver 的父类 ObserverWrapper 定义了 mLastVersion 为-1 。在数据最后进行分发的时候,mLastVersion 是小于 mVersion 的,所以未拦截,然后进行了数据的分发。

    然后就产生了粘性事件。

    作者:不说话的匹诺槽
    转载于:https://juejin.cn/post/7074542604167151647
    如有侵权,请联系删除!

    相关文章

      网友评论

        本文标题:一文读懂LiveData 的粘性事件

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