LiveData的使用和源码分析

简介

LiveData是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能力,即遵循其他引用组件(如Activity,Fragment或Service)的生命周期。这可以保证LiveData仅更新处于活跃生命周期状态的应用组件观察者,例如观察者的生命周期处于STARTEDRESUMED状态,则LiveData会认为该观察者处于活跃状态,只会将更新通知给活跃状态的观察者,非活跃观察者不会收到更改通知。

LiveData的简单使用

  • 创建LiveData实例以存储某种类型的数据,一般LiveData的初始化在ViewModel中完成。
val data:MutableLiveData by lazy {
        MutableLiveData()
    }
  • 创建可定义onChanged()方法的Observe对象,onChanged()在LiveData对象存储的数据发生改变时调用。
  • 使用observe()方法将定义的Observer对象附加到LiveData对象上,这就是我们所说的订阅。
mViewModel.cityData.observe(this, {
           //数据发生改变的时候,执行到这里,可以做相应的处理
        })

更新LiveData对象数

MutableLiveData类通过公开setValue(T)和postValue(T)方法进行更新,其中setValue(T)方法只能在主线程中使用,如果在工作线程需要用到postValue(T)方法来更新LiveData对象。

 cityData.value = tempStr

使用LiveData的优点

  • 确保界面符合数据状态
  • 不会发生内存泄露

观察者会绑定到Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理。

  • 不会因Activity停止而导致崩溃

如果观察者的生命周期处于非活跃状态,则不会收到任何LiveData事件。

  • 不需要手动处理生命周期。

界面组件只需要观察相关数据,不会停止或恢复观察,LiveData将自动管理所有这些操作。

  • 数据始终保持最新状态。

  • 适应配置更改

如果因为配置发生改变,而重新创建了Activity或Fragment,它会立即接收到最新的可用数据。

  • 共享资源

LiveData的源码分析

public abstract class LiveDataLiveData是一个抽象类,不能直接实例化。我们可以使用它的子类MutableLiveData :

public class MutableLiveData extends LiveData {
    //在工作线程中使用
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }
    //在主线程中使用
    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

MutableLiveData提供了postValue()setValue()两个方法,给使用者用来更新数据。这两个方法最后都是分别调用了父类的对应方法,并不没有做什么特别的处理,只是进行了封装。

当初始化实例之后,我么可以通过observe()或者observeForever()方法进行注册。

observeForever()observe()的区别在于,使用observeForever()无论何时,只要数据更新,观察者将收到所有事件,并且永远不会自动删除,需要手动调用removeObserver(Observer)进行移除。而observe()只有在活跃的状态才会接收到。

接下来我们重点分析一下observe()方法:

  • observe()方法

在调用observe()需要传入一个Observer的参数,这是一个回调接口,当时数据发生变动的时候,就会回调用onChanged()方法。

public interface Observer {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}

observer()方法实现的流程:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        //用于判断是否在主线程,说明该方法的调用需要在主线程中调用
        assertMainThread("observe");
        //当前组件状态处于销毁状态的时候,直接返回。(observeForever是没有这个处理逻辑的)
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //实例化一个LifecycleBoundObserver的对象
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //通过健值对的方式进行存储,如果之前没有存储过的则返回为null,如果已经存储过则不为null
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        //判断是否已经添加过了同一个LifecycleOwner
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //不为空,说明已经添加过了,直接返回
        if (existing != null) {
            return;
        }
        //添加一个wrapper,与组件的生命周期发生联系。当生命周期发生改变的时候
        //就回去回调wrapper中的onStateChanged
        owner.getLifecycle().addObserver(wrapper);
    }

在该流程中,可以看到,observer()与组件的生命周期绑定,需要 LifecycleBoundObserver的这个类。接下来对该类进行分析:

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

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

        //重写ObserverWrapper的方法,返回当前的组件是否是活跃的状态(STARTED和RESUMED)
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //当组件生命周期发生变化的时候,回调该方法
        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            //判断组件的生命周期状态是否是DESTROYED
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                //如果是DESTROYED,则移除观察者。
                removeObserver(mObserver);
                return;
            }
            //调用ObserverWrapper的方法
            activeStateChanged(shouldBeActive());
        }

        //重写ObserverWrapper的方法,判断是不是同一个生命周期
        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        //移除当前的对象
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

LifecycleBoundObserver 实现了GenericLifecycleObserver的回调接口,该接口主要用来监听组件生命周期的变化,当组件生命周期发生变化的时候,会回调onStateChanged()的方法。该类还继承了ObserverWrapper。接下来我们继续看看ObserverWrapper

  • ObserverWrapper
    private abstract class ObserverWrapper {
        final Observer mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer observer) {
            mObserver = observer;
        }

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        void activeStateChanged(boolean newActive) {
            //判断状态是否改变,没有则返回
            if (newActive == mActive) {
                return;
            }
            //立即设置为活动状态,因此我们永远不会将任何内容分派到不活动状态

            //设置新的状态
            mActive = newActive;
            //判断当前观察者数量是否为0
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            //如果该组件时活跃的,则mActive+1,否则-1
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                //当活跃观察者的数量从0变为1时调用
                //空方法
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                //当活跃的观察者的数量从1变为0时调用
                //空方法
                onInactive();
            }
            //当组件活跃的时候调用dispatchingValue
            if (mActive) {
                //这个方法最终会调用considerNotify方法更新数据
                dispatchingValue(this);
            }
        }
    }

从上面的流程看到当组件的生命周期发生变动的时候,当组件处于活跃状态的时候会通过dispatchingValue()方法调用到considerNotify(ObserverWrapper observer)

  • considerNotify(ObserverWrapper observer)
  private void considerNotify(ObserverWrapper observer) {
        //如果组件处于非活跃的状态,则直接返回
        if (!observer.mActive) {
            return;
        }
       //继续判断是否处于活跃状态,如果不是,则更新状态并且返回
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //用于判断数据是否更新,因为当调用setValue时mVersion会加1
        //没有更新直接返回
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //更新mLastVersion的值
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        //将数据传给onChange(),会触发接口回调。
        observer.mObserver.onChanged((T) mData);
    }

该方法会调用onChange()方法,而这个方法的实体就是我们在使用的时候创建的Observer()onChange()方法。可以看到这个方法的触发需要满足两个条件:当前的组件处于活跃的状态;数据发生更新;判断数据是否发生更新时通过设置一个计算器 mVersion,在更新数据的时候,进行+1,然后与mLastVersion值进行判断。

  • setValue(T value)
 @MainThread
    protected void setValue(T value) {
        //判断是否是在主线程调用
        assertMainThread("setValue");
        //将 mVersion++;
        mVersion++;
        //更新值
        mData = value;
        //调用该方法,最后会通知观察者进行数据的更新
        dispatchingValue(null);
    }
    //在工作线程中设置值
   //将任务发布到主线程以设置给定值
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        //将任务post到主线程
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
    private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //最后还是通过setValue()设置新的值
            setValue((T) newValue);
        }
    };

虽然postValue()是在工作线程中使用,但是最后还是将任务发送给主线程,然后调用setValue()的方法进行值的更新操作。如果在主线中执行了下面的代码:

liveData.postValue("a");
liveData.setValue("b");

首先将设置值“ b”,然后主线程将使用值“ a”覆盖它。如果在主线程执行发布的任务之前多次调用此方法,则只会分派最后一个值。

以上是LiveData的使用和简单的源码分析。

参考:
https://blog.csdn.net/cs_lwb/article/details/103041866

你可能感兴趣的:(LiveData的使用和源码分析)