Jetpack-LiveData浅析

一、 是什么

Google2018年推出的新架构,意图在统一UI组件与架构。

先说一些前置知识。

  • androidx
    androidx
    它是andorid.support的老弟,android28以后support包的替代品,整合了以前杂乱的东西。
    在项目里用的时候需要做项目迁移,并且设置

编译版本为compile SDK=28
android.useAndroidX=true
android.enableJetifier=true

  • google sample
    谷歌出的相关例子,建议都过一遍。

1.1 业务模式

TODO

1.2 核心组件

涉及框架、生命周期、数据对象等数个组件。
LivaDataViewMoedlRoom等,基本上都已经封装好在androidx包内。
关键的源码不多,建议过一遍源码比较好理解。

1.2.1 LiveData

具体路径是androidx.lifecycle.LiveData。类注释写得很清楚:

LiveData is a data holder class that can be observed within a given lifecycle.

现在我们只把它当作一个holder,可以想象到它将开放的一些方法(外部调用者只需要关心这些)。

set/getData //对持有数据的处理
add/removeObserver //对观察者的处理

Jetpack-LiveData浅析_第1张图片
LiveData类族.png

业务流程

  • 单数据监听
        //1.实例化,设置观察者
        var liveData = object : MutableLiveData() {}
        liveData.observe(this@UserActivity, androidx.lifecycle.Observer {
            System.out.println(it)
        })
        //2.通知数据变化
        liveData.value="changed"//主线程
        liveData.postValue("post changed")//子线程
  • 多数据监听
        //1.实例化
        var liveFirstData = object : MutableLiveData() {}
        liveFirstData.observe(this@UserActivity, androidx.lifecycle.Observer {
            System.out.println(it)
        })
        var liveSecondData = object : MutableLiveData() {}
        liveSecondData.observe(this@UserActivity, androidx.lifecycle.Observer {
            System.out.println(it)
        })
        //2.设置观察者
        var mediatorLiveData = MediatorLiveData()
        mediatorLiveData.addSource(liveFirstData) {
            System.out.println(it)
        }
        mediatorLiveData.addSource(liveSecondData) {
            System.out.println(it)
        }
        //3.通知数据变化
        liveFirstData.value="changed"//主线程
        liveSecondData.postValue("post changed")//子线程

这个突然出现的MutableLiveData是什么?它是LiveData的子类,下边会说。TODO

理解的关键点之一:绑定LiveData的观察者以及它的生命周期
绑定观察者的方法是observe(LifecycleOwner,Observer)observeForever(Observer)

区别在于前者会关联owner的生命周期,而且在DESTROYED状态会移除观察者;
而后者不会自动移除观察者,必须手动移除。

    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer)
    {
        assertMainThread("observe");
        //绑定时先检测生命周期
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //构建封装类
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, 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;
        }
        //绑定封装类为观察者
        owner.getLifecycle().addObserver(wrapper);
    }
    
        @MainThread
    public void observeForever(@NonNull Observer observer) {
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);//触发一次数据分发
    }
    

这里涉及到两个类,LifecycleOwnerObserver。后者就是普通的观察者,即用户自定义的业务事件。

前者是LiveCycle的封装类,androidx中的FragmentActivity都实现了LifeCycle
传入LifecycleOwner主要是为了与生命周期事件绑定。

拿到LifecycleOwner后,LiveData会构建其封装类。同类型的封装类有两个,都是LiveData的非静态类。

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver
private class AlwaysActiveObserver extends ObserverWrapper {

它们的基类ObserverWrapper主要用来1.管理观察者的数据版本,以及2.封装了由观察者生命周期改变而发起的数据分发的触发机制。

    private abstract class ObserverWrapper {
        final Observer mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;//在LiveData代码体现

        ObserverWrapper(Observer observer) {
            mObserver = observer;
        }
        
        //影响持有该观察者的LiveData判定【针对该观察者的数据分发行为,是否与其生命周期关联】
        //AlwaysActiveObserver返回true
        //LifecycleBoundObserver返回大于STARTED
        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        /*
        *主要用于绑定观察者时自动进行的那一次数据分发
        *@param @newActive 新状态是否是活跃
        */
        void activeStateChanged(boolean newActive) {
            //状态未更新直接返回
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            //注意这里更新了当前livedata的活跃观察者的数量
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            //如果liveData之前是非活跃态,而当前观察者是活跃态
            if (wasInactive && mActive) {
                onActive();
            }
            //如果本次更新后liveData切到非活跃态,且当前观察者也是非活跃的
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            //数据分发
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

LiveData通常会直接调用observer.activeStateChanged(newActive)触发数据分发。从上面代码看出来,newActive除了影响是否分发,还影响onActiveonInactive

理解的关键点之二:LiveData的数据分发流程

  • 数据分发流程

1.第一次:绑定永久观察者时自动触发一次数据分发;绑定生命周期关联的观察者时由系统触发数据分发;
2.第n次:持有者调用set/postValue触发消息分发;
3.每当mData被改变,LiveData内部增加数据的版本号mVersion
4.遍历并比较mObservers.mLastVersion,通知较小版本号的观察者(版本号小说明观察者当前拿到的并不是最新数据)
5.LiveData自身持有观察者Observer的引用,在需要时调用observerWrapper.onChanged(T)通知观察者。

  • 外部主动调用触发的数据分发


    Jetpack-LiveData浅析_第2张图片
    手动通知的数据分发.png
    //数据改变时增加版本号
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);//传null是通知所有观察者
    }
    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, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        //检查有没有异步
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
    
    private void considerNotify(ObserverWrapper observer) {
        ...
        //通知之前检测版本号
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

数据分发的起始点之一是setValue函数,其中调用了dispatchingValue。后者内部用到了两个实例级别的标志位mDispatchingValue(正在分发数据)mDispatchInvalidated(分发数据无效化、需要重新分发)

  • 生命周期事件触发的消息分发


    Jetpack-LiveData浅析_第3张图片
    生命周期关联的数据分发.png
        
    //由系统调用的方法 Called when a state transition event happens.
    //LiveData.LifecycleBoundObserver 在观察到状态改变时会先检查生命周期
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }
  • 绑定永久观察者1触发的数据分发


    Jetpack-LiveData浅析_第4张图片
    非生命周期关联的数据分发.png

比较简单,上面代码有提到。

  • 多线程场景下的数据分发

在多线程的情况下,标志位会阻止后来的线程进入数据分发的流程,同时将mDispatchInvalidated(分发数据无效化、需要重新分发)置为true
同时先到的线程在对initiator或者全局观察者完成分发后,会重新判定mDispatchInvalidated无效化标记(见上图32行),触发新一轮的数据分发操作,这样保证了即使在多线程的场景下新数据也不会被漏发。

LiveData的原理真的大概就这些。


1.2.2 常用的LiveData子类MediatorLiveData

TODO

参考

William_Huang-LiveData的onActive()和onInactive()

你可能感兴趣的:(Jetpack-LiveData浅析)