Android Jetpack架构组件带你了解LiveData(原理篇)

Posted 刘望舒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Jetpack架构组件带你了解LiveData(原理篇)相关的知识,希望对你有一定的参考价值。


本文首发于微信公众号「后厂技术官」

前言

在上一篇文章中我们学习了LiveData的基本用法,我们知道LiveData是一个可观察的数据持有者,他是具有组件生命周期感知的,那么它是如何观察组件生命周期变化的呢?LiveData和RxJava的不同的是,LiveData并不是通知所有观察者,它只会通知处于Active状态的观察者,如果一个观察者处于DESTROYED状态,它将不会收到通知,这一点又是如何做到的?还有另外一点,Transformations的map方法其内部进行了什么操作?等等问题,会在这篇文章中给大家进行讲解。

1.LiveData如何观察组件生命周期变化

通过调用LiveData的observe方法来注册观察者,LiveData的observe方法如下所示。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

 @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) 
        assertMainThread("observe");
        //如果被观察者的当前的状态是DESTROYED,就return
        if (owner.getLifecycle().getCurrentState() == DESTROYED) //1
            return;
        
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//2
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);//3
        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);//4
    

注释1处的owner实际上就是注册时传进来来组件,比如Activity,获取组件当前的状态,如果状态为DESTROYED,那么直接return,这说明DESTROYED状态的组件是不允许注册的。

如果你还不了解Lifecycle的状态,可以查看Android Jetpack架构组件(三)带你了解Lifecycle(原理篇)这篇文章。
注释2处新建了一个LifecycleBoundObserver包装类,将owner和observer传了进去。
注释3处将observer和LifecycleBoundObserver存储到SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers中,putIfAbsent方法和put方法有区别,如果传入key对应的value已经存在,就返回存在的value,不进行替换。如果不存在,就添加key和value,返回null。
如果等于null,在注释4处会将LifecycleBoundObserver添加到Lifecycle中完成注册,这样当我们调用LiveData的observe方法时,实际上是LiveData内部完成了Lifecycle的观察者的添加,这样LiveData自然也就有了观察组件生命周期变化的能力。

2.LiveData的observe方法回调

LifecycleBoundObservers是LiveData的内部类,代码如下所示。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

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

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

        @Override
        boolean shouldBeActive() 
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) 
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) 
                removeObserver(mObserver);//1
                return;
            
            activeStateChanged(shouldBeActive());//2
        

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

        @Override
        void detachObserver() 
            mOwner.getLifecycle().removeObserver(this);
        
    
        

LifecycleBoundObserver继承了ObserverWrapper类,重写了shouldBeActive方法,用于判断当前传入的组件的状态是否是Active的,Active状态包括STARTED和RESUMED状态。

LifecycleBoundObserver实现了GenericLifecycleObserver接口,当组件状态发生变化时,会调用onStateChanged方法,当组件处于DESTROYED状态时,会调用注释1处的removeObserver方法,来移除observer。
这样在文章开头的疑问就解决了,为什么一个观察者(组件)处于DESTROYED状态时,它将不会收到通知。

接着会调用注释2处的activeStateChange方法,代码如下所示。

frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

  private abstract class ObserverWrapper 
        final Observer<? super T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

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

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) 
            return false;
        

        void detachObserver() 
        

        void activeStateChanged(boolean newActive) 
            if (newActive == mActive) 
                return;
            
            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);//1
            
        
    

activeStateChanged方法定义在抽象类ObserverWrapper中,它是Observer的包装类,activeStateChanged方法会根据Active状态和处于Active状态的组件的数量,来对onActive方法和onInactive方法回调,这两个方法用于拓展LiveData对象。注释1处,如果是Active状态,会调用dispatchingValue方法,并将自身传进去。

  private void dispatchingValue(@Nullable ObserverWrapper initiator) 
        //正在处于分发状态中
        if (mDispatchingValue) 
            //分发无效
            mDispatchInvalidated = true;//1
            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;
    

mDispatchingValue用于标记当前是否处于分发状态中,如果处于该状态,则在注释1处标记当前分发无效,直接return。一路调用过来,ObserverWrapper是不为null的,ObserverWrapper为null的情况第3小节会讲到,无论是那种情况,都会调用considerNotify方法,代码如下所示。

    private void considerNotify(ObserverWrapper observer) 
        if (!observer.mActive) //1
            return;
        
        if (!observer.shouldBeActive()) 
            observer.activeStateChanged(false);//2
            return;
        
        if (observer.mLastVersion >= mVersion) 
            return;
        
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);//3
    
    

considerNotify方法中做了多次的判断,注释1处,如果ObserverWrapper的mActive值不为true,就直接return。注释2处,如果当前observer对应组件的状态不是Active,就会再次调用activeStateChanged方法,并传入false,其方法内部会再次判断是否执行onActive方法和onInactive方法回调。如果判断条件都满足会调用Observer的onChanged方法,这个方法正是使用LiveData的observe方法的回调。

3.postValue/setValue方法分析

当调用MutableLiveData的observe方法后,还需要通过postValue/setValue方法来更新数据。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

...
  private final Runnable mPostValueRunnable = new Runnable() 
        @Override
        public void run() 
            Object newValue;
            synchronized (mDataLock) 
                newValue = mPendingData;
                mPendingData = NOT_SET;
            
            //noinspection unchecked
            setValue((T) newValue);//1
        
    ;
    ...
    protected void postValue(T value) 
        boolean postTask;
        synchronized (mDataLock) 
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        
        if (!postTask) 
            return;
        
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);//2
    
    
    @MainThread //3
    protected void setValue(T value) 
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    

postValue/setValue方法都定义在LiveData中,根据注释1和注释2处,可以发现postValue方法实际上就是将setValue方法切换到主线程调用。注释3处说明setValue方法是运行在主线程中的,其内部调用了dispatchingValue方法,这个方法在第2小节介绍过,也就是dispatchingValue方法的参数ObserverWrapper为null的情况。
从这里我们可以知道,无论是LiveData的observe方法还是LiveData的postValue/setValue方法都会调用dispatchingValue方法。

4.Transformations.map方法分析

除了以上讲的常用的方法之外,还可能会使用到Transformations.map和Transformations.switchMap方法,这里以Transformations.map为例。这个方法用来在LiveData对象分发给观察者之前对其中存储的值进行更改,
代码如下所示。
frameworks/support/lifecycle/livedata/src/main/java/androidx/lifecycle/Transformations.java

@MainThread
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) 
        final MediatorLiveData<Y> result = new MediatorLiveData<>();//1
        result.addSource(source, new Observer<X>() 
            @Override
            public void onChanged(@Nullable X x) 
                result.setValue(mapFunction.apply(x));
            
        );
        return result;
    

Transformations.map方法运行在主线程,注释1处创建了MediatorLiveData,紧接着调用了它的addSource方法:
support/lifecycle/livedata/src/main/java/androidx/lifecycle/MediatorLiveData.java

  */
    @MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) 
        Source<S> e = new Source<>(source, onChanged);//1
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) 
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        
        if (existing != null) 
            return;
        
        if (hasActiveObservers()) 
            e.plug();//2
        
    

注释1处将传进来的LiveData和onChanged封装到Source类中,注释2处调用了Source的plug方法:

 private static class Source<V> implements Observer<V> 
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<? super V> observer) 
            mLiveData = liveData;
            mObserver = observer;
        

        void plug() 
            mLiveData.observeForever(this);//1
        

        void unplug() 
            mLiveData.removeObserver(this);
        

        @Override
        public void onChanged(@Nullable V v) 
            if (mVersion != mLiveData.getVersion()) 
                mVersion = mLiveData.getVersion();
                mObserver.onChanged(v);//2
            
        
    

注释2处可以看到,Transformations.map方法传入的Observer的回调在这里进行处理。注释1处,Source的plug方法会调用LiveData的observeForever方法,这个和第2小节所讲的内容有什么区别呢?我们再往下看。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

    @MainThread
    public void observeForever(@NonNull Observer<? super T> observer) 
        assertMainThread("observeForever");
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);//1
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) 
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        
        if (existing != null) 
            return;
        
        wrapper.activeStateChanged(true);
    

注释1处用AlwaysActiveObserver来对Observer进行包装,紧接着调用AlwaysActiveObserver的activeStateChanged方法,其内部实际调用的是ObserverWrapper的activeStateChanged方法,这个在第二小节已经做了分析,就不再赘述了。来看AlwaysActiveObserver类是如何定义的。
frameworks/support/lifecycle/livedata-core/src/main/java/androidx/lifecycle/LiveData.java

   private class AlwaysActiveObserver extends ObserverWrapper 
        AlwaysActiveObserver(Observer<? super T> observer) 
            super(observer);
        
        @Override
        boolean shouldBeActive() 
            return true;
        
    

AlwaysActiveObserver是LiveData的内部类,它继承自ObserverWrapper,AlwaysActiveObserver是LiveData的内部类和ObserverWrapper的区别就是,它是永远处于Active状态的。

5.LiveData关联类

接下来给出LiveData关联类的UML图,看明白这个图以后,再回去重新阅读本文,也许你会收获更多。


可以看到,在讲解LiveData时涉及的大部分类都在这个图中,其中MutableLiveData继承自LiveData,LifecycleOwner和Observer和LiveData有关联的关系,ObserverWrapper是Observer的包装类,因此它们有着关联的关系,其他的类大家看图就知道了。


技术官和架构师的聚集地。洞察前沿架构、技术资讯、行业秘闻,聚焦Java、Python、机器学习、大前端等前沿技术。

以上是关于Android Jetpack架构组件带你了解LiveData(原理篇)的主要内容,如果未能解决你的问题,请参考以下文章

Android Jetpack架构组件带你了解LiveData(原理篇)

Android Jetpack架构组件一文带你了解LiveData(使用篇)

Android Jetpack架构组件一文带你了解Lifecycle(原理篇)

Android Jetpack架构组件一文带你了解ViewModel的使用和原理

Android Jetpack架构组件——一文带你了解ViewModel的使用及原理

Android Jetpack架构组件——一文带你了解ViewModel的使用及原理