LiveData分析笔记

LiveData 是一个可感知宿主生命周期变化的组件,在宿主活跃状态下 在宿主执行销毁(DESTROYED)时,自动解除回调,

1.LiveData是怎样实现感知宿主知生命周期的?又是如何自动解除回调的?

2.数据更新后是如何通知观察者的?

3.在宿主处在不活跃状态时做数据更新,待宿主重新处于活跃状态再通知观察者,是怎么实现的?

javascript 复制代码
LivewData<String> data = new MutableLiveData<String>();

data.observe(LifecycleOwner,new Observer<String>(){

void onChanged(String value){
    // update ui
};
});

data.setValue("1111");
data.postValue("2222");

下文列举的源码基于 LivewData-core:2.3.1 版本

observe

less 复制代码
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //执行的线程 非主线程 抛出异常
        assertMainThread("observe");

        //如果宿主是DESTROYED销毁状态,无需操作
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }

        //将LifecycleOwner宿主和observer观察者 包装成一个LifecycleBoundObserver对象
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        
        //将LifecycleBoundObserver对象放到mObservers链表中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

         //返回的existing 不为空,说明当前observer之前已经添加过了
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }

        //使用LifecycleOwner宿主获取LifecycleRegistry,
        //并将LifecycleBoundObserver这个观察者注册到LifecycleRegistry中
        owner.getLifecycle().addObserver(wrapper);
    }

    看看LifecycleBoundObserver包装类的代码

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
       .....
    }

    LifecycleBoundObserver的父类

    private abstract class ObserverWrapper {

        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;
        
        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }
        .....
    }
kotlin 复制代码
到这里,如果知道Lifecycle的实现原理,那么已经可以看出LiveData是怎么感知宿主生命周期的了

分析一下observe方法 做了些啥...

1.线程检查,非主线程不能调用observe

2.检查宿主状态,要是宿主是已经执行onDestory了,那么可以直接return了

3.将LifecycleOwner宿主和observer观察者 包装成一个LifecycleBoundObserver对象

4.将LifecycleBoundObserver对象放到mObservers链表中

5.LifecycleBoundObserver是实现了LifecycleEventObserver接口,那么LifecycleBoundObserver就相当于我们使用
    Lifecycle时候的 LifecycleObserver生命周期观察者

6.将LifecycleBoundObserver这个生命周期观察者注册到LifecycleRegistry中,让它接收LifecycleRegistry派发的生命周期变化事件

既然 LiveData 把内部类 LifecycleBoundObserver作为 生命周期的观察者,那么我们就看看它的onStateChanged里是怎样处理生命周期事件

java 复制代码
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        .....

        //判断宿主是否处于活跃状态
        //最新生命周期状态值是否 >= STARTED,即宿主状态是否为STARTED或者RESUMED
         @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            //获取宿主的生命周期状态值,如处于DESTROYED,那就解除当前观察者
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }

            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                //先判断宿主是否活跃状态,传到activeStateChanged中
                activeStateChanged(shouldBeActive());

                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }
        .......
    }

       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) {
            //当前的状态与上一次状态比较,
            //如果两者一样,则直接return
            if (newActive == mActive) {
                return;
            }
            //记录是否活跃状态
            mActive = newActive;
            changeActiveCounter(mActive ? 1 : -1);

            //如果当前是活跃状态
            if (mActive) {
                //进行数据调度处理
                dispatchingValue(this);
            }
        }
    }    
scss 复制代码
onStateChanged()分析

1.收到宿主生命周期变化后,判断宿主是否DESTROYED,是则解除当前观察者,
  那么到这里已经解答了第一个问题.

2.shouldBeActive()方法是判断宿主当前是否活跃,生命周期状态值是否 >= STARTED视为活跃状态.
    (即宿主生命周期状态是否为STARTED或者RESUMED)  

3.activeStateChanged()中先比较事件前后,活跃状态是否变化
  3.1.如两者相等,说明 活跃状态没有变化,无需执行余下操作

  3.2.如两者不相等,则更新mActive值

  3.3.如mActive为true,代表当前宿主是活跃状态,而上一次是非活跃状态,并使用dispatchingValue()进行数据处理
      
  3.4.那么到这里也就解答了第三个问题,原理就是收到宿主生命周期事件时对比先后的活跃状态,如前后不相等,并且
      当前是活跃,则会进行数据处理(通知LiveData的观察者)

接下来看dispatchingValue()

ini 复制代码
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    //判断当前是否正在执行调度
    if (mDispatchingValue) {
        //标记 设置正在执行的循环调用无效
        mDispatchInvalidated = true;
        return;
    }
    //标记当前正在执行调度
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        //如initiator不为空,只通知指定的initiator观察者
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            // 获取mObservers迭代器,通知所有LiveData的观察者
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                //具体执行某个观察者
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

private void considerNotify(ObserverWrapper observer) {
    //如当前宿主不活跃,不执行通知
    if (!observer.mActive) {
        return;
    }
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    
    //比较 LiveData观察者记录的数据版本号 和 LiveData自身记录的数据版本号
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    //更新观察者的数据版本号
    observer.mLastVersion = mVersion;
    //通知数据更新
    observer.mObserver.onChanged((T) mData);
}      
      

dispatchingValue()分析

arduino 复制代码
   1.mDispatchingValue标记当前是否正在执行事件派发

   2.mDispatchInvalidated标记正在执行的 do-while 循环调用是否有效

   3.do-while 正常情况只执行一遍,但如果正在for循环中,dispatchingValue()被再次调用
     ,那么结合两个标记位,正在执行的for就会退出,并再一次执行do{}

   4.比较两个数据版本号,如观察者记录数据版本号落后于LiveData自身的数据版本号,则通知观察者数据更新
   

postValue:子线程使用

java 复制代码
protected void postValue(T value) {
    boolean postTask;
    //加锁
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

private final Runnable mPostValueRunnable = new Runnable() {
    @SuppressWarnings("unchecked")
    @Override
    public void run() {
        Object newValue;
        //加锁
        synchronized (mDataLock) {
            newValue = mPendingData;
            mPendingData = NOT_SET;
        }
        setValue((T) newValue);
    }
};    

postValue分析

1.postTask的值代表是否有未处理的数据,并将需更新的数据赋值给mPendingData

2.如果postTask为true,则通过Handleg通知主线程执行mPostValueRunnable,
  如果postTask为false,说明上一个数据的mPostValueRunnable还没执行,那么就只需要直接将最新数据赋值给mPendingData
  即可,待主线程Handle处理上一个数据的mPostValueRunnable,mPendingData自然是最新的,这也是LiveData的特性,
  只保持最新的状态数据

3.mPostValueRunnable中将mPendingData在赋值给一个新的对象,并重新将mPendingData置为NOT_SET,
  并待用setValue

setValue

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


1.LiveData的数据版本号mVersion递增1,用于在dispatchingValue的流程中与LifecycleBoundObserver中的数据版本号对比。

以上就是LiveData的实现逻辑分析。 至于数据倒灌出现的原因:

1.主要是LiveData是基于Lifecycle的,而Lifecycle中每添加一个新的LifecycleObserver,就会从INITIALIZED状态至宿主最新的生命周期状态 的这个范围内所有涉及到的生命周期都会回调给LifecycleObserver,那对与LiveData而言就是回调到LifecycleBoundObserver.onStateChanged中

2.LiveData 和 LifecycleBoundObserver 各自版本号不相等,结合第1点,就最终导致数据倒灌。

相关推荐
风槐啊3 小时前
六、Java 基础语法(下)
android·java·开发语言
皮皮虾在睡觉4 小时前
数据库基础04
android·数据库
彭于晏6896 小时前
Android高级控件
android·java·android-studio
肖哥弹架构7 小时前
Vue组件开发:从入门到架构师
前端·vue.js·程序员
666xiaoniuzi11 小时前
深入理解 C 语言中的内存操作函数:memcpy、memmove、memset 和 memcmp
android·c语言·数据库
沐言人生16 小时前
Android10 Framework—Init进程-8.服务端属性文件创建和mmap映射
android
沐言人生16 小时前
Android10 Framework—Init进程-9.服务端属性值初始化
android·android studio·android jetpack
沐言人生16 小时前
Android10 Framework—Init进程-7.服务端属性安全上下文序列化
android·android studio·android jetpack
追光天使16 小时前
【Mac】和【安卓手机】 通过有线方式实现投屏
android·macos·智能手机·投屏·有线