LiveData深入浅出原理分析

Android Architecture Components 系列目录

  1. LiveData原理深入浅出,透过源码看本质
  2. LiveDataBus框架抽丝剥茧后,原来如此简单
  3. Android Room数据库,用过你才知道好

LiveData通过源码看本质

博客创建时间:2021.01.25
博客更新时间:2020.01.26

以Android studio 4.1.1来分析讲解,gradle=6.5,SdkVersion 30。如图文和网上其他资料不一致,可能是别的资料版本较低而已


前言

** 本篇文章适合已能基本使用LiveData,但是具体原理和细节不太清楚的Android开发者。请跟随我的脚步一起探索LiveData的秘密!**

LiveData数据持有类。有如下特性点:

  1. 数据可以被观察者订阅
  2. 能够感知实现LifecycleOwner接口组件的生命周期(如Fragment、Activity、Service),减少内存泄漏。
  3. 可以设定组件处于激活状态(STARTED、RESUMED)才会通知观察者有数据更新,且组件前后台切换后能自动从最新数据开始刷新

原理

其实LiveData的原理非常简单,它的逻辑其实和设置点击监听事件是一样的,其步骤都是如下:

  1. 创建监听实例>>(MainThread中创建Observer)
  2. 对控件View设置监听>>(通过调用observe()或observeForever()对LiveData注册观察者)
  3. 发生点击事件>>(通过调用LiveData的setValue()或postValue()方法改变持有值T)
  4. 监听接口回调View.onClick()>>(LiveData进行数据的分发,最终调用Observer.onChanged()方法进行数据处理)

你能简单的通过Button的点击事件流程快速高效的理解LiveData的原理和调用流程,其实没有想象中的那么高大上。跟着我的脚步我们继续盘它!

属性

  1. mVersion
    LiveData的标识版本,每次数据改动一次则mVersion++,它的作用用于判断T是否已经处理过,处理过的变动将不再做改动。
    private int mVersion = START_VERSION;
  1. mPendingData
    初始值为NOT_SET,它用于作为需要发射变动类型T的中介。当mPendingData ==NOT_SET时,LiveData处于数据准备状态;mPendingData !=NOT_SET,LiveData处于数据Set状态,不可继续Set值。
  private volatile Object mData = NOT_SET;
    volatile Object mPendingData = NOT_SET;
  1. mObservers
    一个LiveData可以注册多个Observe,现实使用情境为多个Actvity中可以注册监听同一个LiveData。

    mObservers 中保存的是Observer和其对应的包装类,根据Observer注册的方式不同,其ObserverWrapper也会不一样

 @SuppressLint("RestrictedApi")
    private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

方法

1. observe(LifecycleOwner owner, Observer<? super T> observer)

注册具有生命周期监听的Observer,它可以安全地观察LiveData而不用担心泄漏,它的生命周期特性表现在

  1. 仅当owner处于Lifecycle.StateSTARTED或Lifecycle.StateRESUMED状态时,观察者才会收到事件。
  2. 如果owner处于 Lifecycle.StateDESTROYED状态,则observer将被自动删除。
  3. 在owner未激活的情况下更改数据时,它将不会收到任何更新。如果再次激活,它将自动接收最新的可用数据。(如Activity在onPause状态无法接收数据,变换为onRresume状态时可以接收数据)
  4. 如果Observer已注册过,但是在次注册时前后的owner不一致,则会抛IllegalArgumentException
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    
    
        // 判断是否在主线程,不在则抛异常
        assertMainThread("observe");
        // owner处于DESTROYED状态则无法进行Observer注册
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
    
    
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 从mObservers中获取LiveData.ObserverWrapper,如果不存在则返回null
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //如果Observer被注册过,但是owner前后不一致,则抛异常。
        if (existing != null && !existing.isAttachedTo(owner)) {
    
    
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
    
    
            return;
        }
        //将wrapper加入observer的观察者列表
        owner.getLifecycle().addObserver(wrapper);
    }

2.observeForever(Observer<? super T> observer)

永久性注册方法,其特性为:

  1. 将给定的观察者添加到观察者列表中。此调用类似于带有生命周期所有者的{@link LiveData observe(LifecycleOwner,Observer)},该生命周期所有者始终处于活动状态。
  2. 给定的观察者将一直接收所有事件,并且永远不会被自动删除。除非手动调用removeObserver(Observer)方法停止
  3. 当LiveData具有此类观察者之一,则它将被视为active
  4. 如果在此之前已将观察者和所有者绑定的ObserverWrapper添加进入LiveData,此次在通过observeForever(Observer)方式注册观察者则抛IllegalArgumentException。
    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
    
    
        //是否在主线程中
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        //判断是否已在mObservers列表中
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // 如果在此之前已将观察者和所有者绑定的ObserverWrapper添加进入LiveData,则抛IllegalArgumentException
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
    
    
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
    
    
            return;
        }
        //设置wrapper更新为active=true
        wrapper.activeStateChanged(true);
    }

3.removeObserver(Observer<? super T> observer)

从观察者列表中删除给定的观察者,该方法应该与observeForever(Observer<? super T> observer)方法成对出现,它一般在onCreate和onDestory中调用

    @MainThread
    public void removeObserver(@NonNull final Observer<? super T> observer) {
    
    
        assertMainThread("removeObserver");
        ObserverWrapper removed = mObservers.remove(observer);
        //observer原本就不存在于mObservers中
        if (removed == null) {
    
    
            return;
        }
        //如果ObserverWrapper含有owner,则将observer从owner的观察者列表中移除
        removed.detachObserver();
        //设置ObserverWrapper的active=false,状态改变为非激活状态
        removed.activeStateChanged(false);
    }

4.removeObservers(@NonNull final LifecycleOwner owner)

删除与给定的{@link LifecycleOwner}关联的所有观察者。


5. postValue(T value)

将任务发布到主线程以设置给定值。该方法可以在非UI线程中执行。如果在主线程执行发布的任务之前多次调用此方法,则只会分派最后一个值。

    protected void postValue(T value) {
    
    
        boolean postTask;
        synchronized (mDataLock) {
    
    
            // true:上一个数据已发送完毕,处于就绪状态
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
    
    
            //上一个数据还未发送完毕,不可发布
            return;
        }
        //在主线程中执行发布任务,修改设置
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

6. setValue(T value)

修改需要发射分发的值,每个值都有对应Version作为唯一id,此处mVersion++后进行值的发布。注意该方法只能运行在主线程中。

    @MainThread
    protected void setValue(T value) {
    
    
        assertMainThread("setValue");
        //修改mVersion,标识每个value
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

如果先后调用

  1. liveData.postValue(“a”);
  2. liveData.setValue(“b”);

首先将设置值“ b”,然后主线程将使用值“ a”覆盖它。


7. onActive()

当active Observer的数量从0变为1时调用


8. onInactive()

当active Observer的数量从1变为0时调用。此时并不意味着mObservers中不含Observer,有可能Observer的owner不处于StateSTARTED和StateRESUMED状态。


9. considerNotify(ObserverWrapper observer)

执行数据更新操作,通过多条件判断最终执行了我们熟悉的Observer.onChanged(T)。

    private void considerNotify(ObserverWrapper observer) {
    
    
        //确保ObserverWrapper是mActive=ture才能继续执行
        if (!observer.mActive) {
    
    
            return;
        }
        //确保当前生命周期处于允许状态,可继续执行后续代码
        if (!observer.shouldBeActive()) {
    
    
            observer.activeStateChanged(false);
            return;
        }

        //数据未发射处理过方可进行后续操作
        if (observer.mLastVersion >= mVersion) {
    
    
            return;
        }
        observer.mLastVersion = mVersion;
        //进行数据刷新
        observer.mObserver.onChanged((T) mData);
    }

10. dispatchingValue(@Nullable ObserverWrapper initiator)

数据变更后的分发发射方法。当某一个ObserverWrapper第一次在LiveData中注册时,会自动发布最新的数据。所以要注意在Observer.onChanged(T)中做好NullPointerException预防

    @SuppressWarnings("WeakerAccess") /* synthetic access */
    void dispatchingValue(@Nullable ObserverWrapper initiator) {
    
    

        ......
        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;
                }
            }
        }
        ......

    }

内部类

在LiveData中有三个Observer包装类,ObserverWrapper、AlwaysActiveObserver和LifecycleBoundObserver,后两者是前者的子类。

在LiveData的两个两个注册方法中,其Observer有不同特性性很大的关系在于对应的Observer包装类不一样。

1. ObserverWrapper

AlwaysActiveObserver和LifecycleBoundObserver的父类,是一种带自定义属性的Observer包装类。

    /**
     * Observer包装类
     */
    private abstract class ObserverWrapper {
    
    
        //每个包装类都含有一个Observer
        final Observer<? super T> mObserver;
        // Observer活动状态active标识,只有处于活动状态的Observer,才能发射数据
        boolean mActive;
        // Observer的version标识
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
    
    
            mObserver = observer;
        }

        //是否应该处于Active
        abstract boolean shouldBeActive();

        /**
         *是否Attached了owner
         */
        boolean isAttachedTo(LifecycleOwner owner) {
    
    
            return false;
        }

        /**
         * 分离owner,需要子类中重写
         */
        void detachObserver() {
    
    
        }

        /**
         * active 激活状态的更改,条件达到会调用LiveData的onActive()和onInactive()方法
         * 1.当newActive=true时,LiveData中的活跃数量mActiveCount由0变为1时,调用onActive(),同时发布值dispatchingValue(this)
         * 2.当newActive=false时,LiveData中的活跃数量mActiveCount由1变为0时,调用onInactive()
         */
        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.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
    
    
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
    
    
                onInactive();
            }
            if (mActive) {
    
    
                dispatchingValue(this);
            }
        }
    }

注意:

  • boolean mActive是标识ObserverWrapper中的Observer是否可用,一般注册后就会变为true,移除后就会变为false。
  • boolean shouldBeActive()是根据绑定的LifecycleOwner的指定生命周期股则来确定的,如果没有绑定LifecycleOwner则表明任意生命周期状态都为true。

2. AlwaysActiveObserver

重写了shouldBeActive()方法,保持AlwaysActiveObserver持有的Observer的活跃状态active始终为true。

AlwaysActiveObserver是observeForever(observer)方法中注册的指定ObserverWrapper。

    /**
     * 总是处于活跃状态的 Observer包装类
     */
    private class AlwaysActiveObserver extends ObserverWrapper {
    
    
        AlwaysActiveObserver(Observer<? super T> observer) {
    
    
            super(observer);
        }

        @Override
        boolean shouldBeActive() {
    
    
            return true;
        }
    }

3. LifecycleBoundObserver

顾名思义,生命周期约束ObserverWrapper。方法observe( LifecycleOwner , observer)中指定注册的ObserverWrapper。

    /**
     * 生命周期约束Observer
     */
    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    
    
        @NonNull
        final LifecycleOwner mOwner;

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

        /**
         * 确定Observer在处于STARDED和RESUMED状态时,处于活动状态
         */
        @Override
        boolean shouldBeActive() {
    
    
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        /**
         * 相较父类的方法多了一层判断,当mOwner处于DESTROYED状态时自动将Observer从LiveData的观察者列表mObservers中移除
         */
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
    
    
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
    
    
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
    
    
            return mOwner == owner;
        }

        /**
         * 移除在mOwner观察列表中的LifecycleBoundObserver
         */
        @Override
        void detachObserver() {
    
    
            mOwner.getLifecycle().removeObserver(this);
        }

    }

总结

  1. LiveData中的观察者注册和数据刷新处理必须运行在MainThread中。因为其原理相当于在MainThread新建了一个LiveData变量,所有的LiveData相关的操作实际都是运行在主线程中的。

  2. 当LiveData调用onInactive时,LiveData中没有actively的观察者可以释放任何繁重的资源。


相关链接

  1. LiveData原理深入浅出,透过源码看本质
  2. LiveDataBus框架抽丝剥茧后,原来如此简单
  3. Android Room数据库,用过你才知道好

博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !

猜你喜欢

转载自blog.csdn.net/luo_boke/article/details/113173672