美文网首页
Jetpack 源码分析(二) - LiveData源码分析

Jetpack 源码分析(二) - LiveData源码分析

作者: 琼珶和予 | 来源:发表于2020-04-12 22:22 被阅读0次

      距离上一篇文章差不多有一个月,感觉进度有点慢。唉,在这一个月里面,自己有点颓废啊!这篇文章居然拖了这么久。废话少说,今天我们就来学习一下Jetpack中的LiveData,研究一下它的原理。
      本文参考资料:

    1. LiveData 概览
    2. ViewModels and LiveData: Patterns + AntiPatterns
    3. LiveData beyond the ViewModel — Reactive patterns using Transformations and MediatorLiveData
    4. LiveData with SnackBar, Navigation and other events (the SingleLiveEvent case)
    5. How and where to use Transformations.switchMap?

      注意,本文LiveData的所有源码均来自于2.0.0版本

    1. 概述

      在正式分析LiveData之前,我们先来了解一下LiveData是一个什么东西吧(虽然大家可能都知道),不过我还是多说几句。
      从官方文档的介绍来看的话,LiveData是一个可观察的数据存储器类。但是与普通可观察类不同的是,LiveData是能感知组件(Activity 、Fragment或者Service等)的生命周期。正因为拥有这个感知能力,使得LiveData在组件Destroy时能自动移除观察者对象,这样便能避免很多NPE和内存泄漏的问题。
      LiveData的优点还有很多,这里就不过多的介绍,有兴趣的同学可以看看官方文档:LiveData 概览,官方文档介绍的非常详细。
      本文从LiveData的基本使用开始,由浅入深的介绍LiveData的方方面面。同时由于本系列文章还未介绍ViewModel,所以本文LiveData的所有例子都在放在Activity中,但是按照官方推荐,LiveData和ViewModel结合使用,希望大家不要被我的例子误导。
      本文打算从如下几个方面来介绍LiveData:

    1. LiveData的基本使用。
    2. LiveDdata的原理分析,其中会着重分析几个点:1. Version的控制,LiveData是怎么知道哪些Observer需要通知,哪些Observer不需要通知;2. LiveData是怎么实现只在活跃状态下才会通知Observer,同时又是如何实现从非活跃状态变为活跃状态会通知Observer;3. LiveData是怎么实现在组件Destroy时自动移除所有的Observer;4. onActive方法和onInactive方法的作用和回调时机。
    3. MediatorLiveData的基本使用和实现原理、以及怎么merge多个LiveData的数据。
    4. Transformationsmap方法和switchMap方法的区别和实现原理。

    1. LiveData 的基本使用

      首先,我们先来看看LiveData是怎么使用的:

    class LiveDataDemoActivity : AppCompatActivity() {
    
        private lateinit var mTextView: TextView
        private lateinit var mButton: Button
        private val mTextLiveData: MutableLiveData<String> = MutableLiveData()
        private var mUpdateCount = 0
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_live_data_demo)
            mTextView = findViewById(R.id.textView)
            mButton = findViewById(R.id.button)
            mTextLiveData.observe(this, Observer {
                mTextView.text = it
            })
            mButton.setOnClickListener {
                mTextLiveData.value = "update content ${mUpdateCount++}"
            }
        }
    }
    

      上面的例子展示了一个简单的效果,当我们点击Button时,更新TextView显示的内容。相比较于以前的例子,我们这个例子不会直接操作TextView来实现更新的,而是更新LiveData,间接的更新了TextView显示的内容。可能有人在想,这不是多此一举吗?
      答案当然是否定的,这样做有一个很多的好处,就是实现了View层和Model层的解耦。这样来想,如果Model层很多地方都需要更新TextView的内容,岂不是都要持有TextView的引用吗?而有了LiveData之后,只需要持有LiveData对象即可。这样就不会导致内存泄漏和空指针异常。简而言之,LiveData就是数据驱动,数据更新了,对应的UI也跟着更新。
      切记,真实开发不应该把LiveData直接放在View层。它应该放在Model层,用来连接View层和Mode层。
      同时,我们可以从上面的例子中发现一个小细节,我们并没有在Activity的onDestroy方法里面去remove它的Observer。这是因为,LiveData它会自己监听组件的生命周期,当组件Destroy时,会自动remove Observer,从而避免空指针异常。
      如上便是LiveData的基本使用,是不是很简单的?确实比较简单,我们还有很多扩展使用没有介绍,这些都会在后面的内容中介绍。

    2. LiveData的原理分析

      我们已经了解了LiveData的基本使用,至此我们就来分析它的源码。我们先来看看几个方法:

    方法名 解释
    observe observe是LiveData非常重要的一个方法,作用是给LiveData添加一个
    观察者对象(Observer)。这个方法两个参数,其中第一个参数是
    LifecycleOwner对象,表示LiveData需要感知它的生命周期。
    observeForever 与observe方法相同作用还有一个observeForever方法。该方法跟
    observe方法有一个很大的区别就是,通过该方法不需要感知组
    件的生命周期,也就是无论在何时更新了数据,通过该方法添加
    的Observer都会被通知到。使用该方法需要注意的是:必须在适
    当的时机中调用removeObserver方法,用来remove对应的Observer。

    (1). observe方法

      我们先来看看observe方法的源码:

        @MainThread
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> 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);
        }
    

      observe方法只要分为如下几步:

    1. check 组件的生命中周期。如果组件的生命已经处于Destroy状态,没有必要再添加Observer。
    2. 将传递进来的两个参数包装成一个LifecycleBoundObserver对象,同时检查该Observer是否已经添加到其他组件里面,如果已经添加, 则会抛出IllegalArgumentException
    3. LifecycleOwner添加一个Lifecycle的观察者对象(即LifecycleBoundObserver 对象)。从这里,我们可以看出来,LifecycleBoundObserver的本质就是一个LifecycleObserver

    (2). observeForever方法

      看完了observe方法的实现,我们再来看看observeForever:

        @MainThread
        public void observeForever(@NonNull Observer<? super T> observer) {
            assertMainThread("observeForever");
            AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
            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);
        }
    

      跟observe方法相比,observeForever方法主要有两个区别:

    1. 使用AlwaysActiveObserver来监听生命周期。同时从AlwaysActiveObserver 的实现中,我们可以看出来,shouldBeActive方法永远为true,表示说是AlwaysActiveObserver永远能够接受到通知的。
    2. 直接调用了activeStateChanged用来更新状态,并且尝试着通知Observer。而observe方法是通过监听生命周期进而间接的回调activeStateChanged方法。

    (3).ObserverWrapper和LifecycleBoundObserver

      在正式了解LifecycleBoundObserver之前,我们先来看看它的uml类图吧。


      在我们了解了Lifecycle之后,我们知道生命周期的回调是在onStateChanged方法里面。所以,我们来看看LifecycleBoundObserveronStateChanged方法的实现:
            @Override
            public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
                if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                    removeObserver(mObserver);
                    return;
                }
                activeStateChanged(shouldBeActive());
            }
    

      从上面的代码中,我们可以得到一个信息,就是当组件(Activity、Fragment等)Destroy时,LiveData会自动移除对应的Observer,这恰好与我们前面所说的内容与之呼应。其次,我们会发现onStateChanged方法里面回调的是activeStateChanged方法,我们来看看这个方法:

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

      activeStateChanged方法主要分为如下几步:

    1. 如果状态就是最新状态,那么表示更新通知过所有的Observer,没必要再通知了。比如说,在Activity的onStart和onResume的两个生命周期里面,都会回调activeStateChanged方法,并且newActive都为true,当我们已经在onStart通知过了,在onResume时就没必要再通知了。
    2. 更新LiveData的mActiveCount,mActiveCount表示的就是LiveData活跃的Observer。如果LiveData活跃的Observer为0,同时该Observer将更新为活跃状态,那么就会回调LiveData的onActive方法;反之,如果该Observer变为非活跃状态,同时mmActiveCount为0,则回调onInActive方法。
    3. 如果该Observer更新到活跃状态,会调用dispatchingValue方法,去尝试通知每个Observer更新数据。

      我们来看看dispatchingValue方法:

        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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                            mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                        considerNotify(iterator.next().getValue());
                        if (mDispatchInvalidated) {
                            break;
                        }
                    }
                }
            } while (mDispatchInvalidated);
            mDispatchingValue = false;
        }
    

      在dispatchingValue方法中,我们需要如下2点:

    1. initiator为null和不为null的区别。其中initiator为null,则会遍历所有的Observer,然后尝试所有的Observer;initiator不为null,则只会通知initiator对象中持有的Observer。这种情况,我们可以简单的理解为局部通知和全局通知。那么什么时候为null,什么时候不为null。纵观整个LiveData的源码,当我们通过setValue和postValue方法更新LiveData持有的数据时,此时initiator为null,则会通知所有的Observer;当时Observer新添加到LiveData中来,或者Activity和Fragment生命周期变化了,此时initiator不为null,此时就是ObserverWrapper 通知自己内部持有的Observer。
    2. mDispatchingValuemDispatchInvalidated这两个变量设计的非常巧妙。当第一个ObserverWrapper 调用dispatchingValue方法时,此时mDispatchingValue将设置为true,mDispatchInvalidated会未设置为false。如果第一个ObserverWrapper 还未执行完dispatchingValue方法,第二个ObserverWrapper因为部分原因(比如数据更新了或者生命周期变换了)也来调用dispatchingValue,此时它会将第一个ObserverWrapper的调用全部失效,即mDispatchInvalidated设置为true,然后让第一个ObserverWrapper 重新遍历通知所有的Observer。这样能保证每个Observer能收到最新的通知,接受到最新的数据。

      我们知道,在dispatchingValue方法中并没有真正的Observer回调方法。真正回调Observer的方法的地方是在considerNotify方法里面。我们来看看:

        private void considerNotify(ObserverWrapper observer) {
            if (!observer.mActive) {
                return;
            }
            // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
            //
            // we still first check observer.active to keep it as the entrance for events. So even if
            // the observer moved to an active state, if we've not received that event, we better not
            // notify for a more predictable notification order.
            if (!observer.shouldBeActive()) {
                observer.activeStateChanged(false);
                return;
            }
            if (observer.mLastVersion >= mVersion) {
                return;
            }
            observer.mLastVersion = mVersion;
            //noinspection unchecked
            observer.mObserver.onChanged((T) mData);
        }
    

      considerNotify方法主要分为如下几步:

    1. 判断ObserverWrapper 是否活跃状态,如果不是活跃状态,则不用通知更新。
    2. 判断当前组件是否处于活跃状态,如果不是活跃状态,则调用activeStateChanged方法,将当前ObserverWrapper设置为非活跃状态。可能有人有疑问,前面我们已经判断是否活跃,为啥在这里还要判断组件是否为活跃状态,这俩不是同步的吗?从Google爸爸的注释来看,可能存在组件已经更新了状态,但是我们还没有收到对应的Event来更新ObserverWrapper的状态。至于具体是什么情形呢?官方也没有给出准确的答案,对此我也有疑问。
    3. 判断当前ObserverWrapper的Version,如果当前的Version大于等于LiveData本身的版本,表示当前ObserverWrapper已经通知更新了,不需要再通知。
    4. 调用Observer的onChanged方法。在这里,我们终于看到了真正的回调。

      对于onChanged方法回调的路径真是不容易,由于过程比较繁琐,我在这里简单的总结。

    onChanged方法调用路径主要分为两条:

    1. LifecycleBoundObserver # onStateChanged -> LifecycleBoundObserver # activeStateChanged -> LiveData # dispatchingValue -> LiveData # considerNotify。此条路径主要处理的case是组件生命周期的变化。其中activeStateChanged方法保证了只有处于活跃状态Observer才会收到通知;dispatchingValue方法保证此条路径自己一个Observer收到通知;considerNotify方法再次保证处于活跃的Observer才会通知,同时还保证了一个Observer对于同一次更新收到一次通知(使用Version控制的)。
    2. LiveData # setValue -> LiveData # dispatchingValue -> LiveData # considerNotify 。此条路径处理的case是外部条件更新LiveData持有的数据。其他地方跟路径1类似,唯一区别就是在considerNotify会通知所有的Observer。

    3. MediatorLiveData的基本使用和原理分析

      说完了最基本的LiveData,我们再来看看它的一个子类--MediatorLiveData。用我们上面的那个例子,假设TextView显示的内容不是被一个LiveData控制的,而是多个,比如说10个,我们应该怎么实现呢?有一个简单的方法就是定义10个LiveData,同时监听这10个LiveData的变化。
      对于这种方法的好与坏我不置可否,但是有一点,我需要提出来。我们都知道,LiveData是被定义ViewModel,View层从VIewModel里面获取LiveData从而监听。像上面的解决方法,我们就要从ViewModel获取这10个LiveData,想一想这代码会写成什么样子?那么有没有一种办法能帮助获取一个LiveData对象就能监听这个10个LiveData的变化,那当然就要让MediatorLiveData出手了。

    (1). MediatorLiveData的基本使用

      MediatorLiveData的作用就是合并多个LiveData源,我们先来看看它是怎么使用的吧。

    class MediatorLiveDataDemoActivity : AppCompatActivity() {
    
        private lateinit var mTextView: TextView
        private lateinit var mButton: Button
        private val mTextLiveData: MutableLiveData<String> = MutableLiveData()
        private val mText2LiveData: MutableLiveData<String> = MutableLiveData()
        private val mMergeTextLiveData: MediatorLiveData<String> = MediatorLiveData();
        private var mUpdateCount = 0
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_mediator_live_data_demo)
            mTextView = findViewById(R.id.textView)
            mButton = findViewById(R.id.button)
            mButton.setOnClickListener {
                if (mUpdateCount % 2 == 0) {
                    mTextLiveData.value = "update content ${mUpdateCount++}"
                } else {
                    mText2LiveData.value = "update content ${mUpdateCount++}"
                }
            }
        }
    
        private fun observeV1() {
            mTextLiveData.observe(this, Observer {
                mTextView.text = it
            })
            mText2LiveData.observe(this, Observer {
                mTextView.text = it
            })
        }
    
        private fun observeV2() {
            val observer = Observer<String> {
                mMergeTextLiveData.value = it;
            }
            mMergeTextLiveData.addSource(mTextLiveData, observer)
            mMergeTextLiveData.addSource(mText2LiveData, observer)
            mMergeTextLiveData.observe(this, Observer {
                mTextView.text = it
            })
        }
    }
    

      这里我将普通实现方案(即observeV1方法)和MediatorLiveData实现方案(即observeV2方法)。从具体实现的代码,虽然V2的代码比V1的多,但是V2更加收敛,我们只要知道mMergeTextLiveData的存在即可,不需要管TextView的内容具体由几个LiveData控制的。

    (2). MediatorLiveData的原理

      从本质来看,MediatorLiveData就是一个LiveData,所以LiveData有的特点,MediatorLiveData都有。那么,我们直接来看一下,MediatorLiveData独有的特点,就是能够合并多个LiveData源,我们去瞧瞧是怎么实现的。
      我们直接从addSource方法入手,看看其内部的实现:

        public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
            Source<S> e = new Source<>(source, onChanged);
            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();
            }
        }
    

      addSource方法内部做的事情非常的少,总结起来就是分为两步:

    1. 将传递进来的LiveData和对应的Observer包装成一个Source对象。
    2. 如果此时MediatorLiveData已经有活跃的Observer,就表示此时对应的组件已经处于活跃状态了,那么就是调用plug方法。

      我们从addSource方法看不出来有啥特殊的地方,我们要想知道MediatorLiveData是怎么同时监听多个LiveData,必须从Source下手。

        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);
            }
    
            void unplug() {
                mLiveData.removeObserver(this);
            }
    
            @Override
            public void onChanged(@Nullable V v) {
                if (mVersion != mLiveData.getVersion()) {
                    mVersion = mLiveData.getVersion();
                    mObserver.onChanged(v);
                }
            }
        }
    

      Source的实现非常的简单,内部持有一个LiveData对象和一个Observer对象。同时我们看到的是,在plug方法里面,通过调用LiveData的observeForever方法用来监听LiveData的变化。当LiveData持有的数据发生了变化,会回调Source的onChanged方法,onChanged方法会调用内部持有的Observer的onChanged方法,从而调用到外面我们定义的Observer对象中去。在那里,我们做了一件事--件更新的值设置到MediatorLiveData中去,由于我们监听了MediatorLiveData,所以所有LivaData变化都会经过MediatorLiveData更新到TextView上去。
      从这里,我们可以看出来,MediatorLiveData类似于一个主管道,所有子管道的更新到都会流到这个主管道中去。

    (3). 如何使用MediatorLiveDatamerge多个LiveData呢?

      我们知道在RxJava,zip操作符可以将两个数据流合并成一个数据流,再传递到下游去。LiveData中并没有现成的API供我们使用,所以需要自我实现。下面我将贴出一个简单的Demo来展示如何实现的,主要思路来源于:LiveData beyond the ViewModel — Reactive patterns using Transformations and MediatorLiveData

    fun <T, A, B> LiveData<A>.mergeOtherLiveData(
        other: LiveData<B>,
        onChanged: (A, B) -> T
    ): MediatorLiveData<T> {
        val result = MediatorLiveData<T>()
        val mergeInvoker = {
            val selfValue = this.value
            val otherValue = other.value
            if (selfValue != null && otherValue != null) {
                result.value = onChanged(selfValue, otherValue)
            }
        }
        result.addSource(this) {
            mergeInvoker.invoke()
        }
        result.addSource(other) {
            mergeInvoker.invoke()
        }
        return result
    }
    

      这里,我给LiveData定义了一个扩展方法,主要就是通过MediatorLiveData实现的,具体实现也比较简单,这里就不解释。我们来看一下怎么使用的:

    class MergeLiveDataActivity : AppCompatActivity() {
    
        private val mAvatarLiveData: MutableLiveData<Avatar> = MutableLiveData()
        private val mIntroductionLiveData: MutableLiveData<Introduction> = MutableLiveData()
        private lateinit var mUserLiveData: MutableLiveData<User>
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            mUserLiveData =
                mAvatarLiveData.mergeOtherLiveData(mIntroductionLiveData) { avatar, introduction ->
                    User(avatar, introduction)
                }
        }
    }
    

      在这里,我简单的定义了一个User类。其中User类内部分为两个部分:Avatar和Introduction。我们可以这样来假设,在实际开发中有两个请求分别这两部分的数据,只有等待两个请求回来时,才算是User信息请求完成。所以,这里我们通过mergeOtherLiveData方法来合并两个LiveData的数据。

    4. Transformations的map方法和switchMap方法的区别和实现原理

      我们在使用LiveData时,有一个场景应该是非常常见的--类型映射,比如说从A类型映射到B类型。这里我们就需要了解map和switchMap。

    (1).map方法

      假设,有一个LiveData<User>对象,我们想要从中获取User的name和age拼接成一个String,这个应该怎么办呢?普通的方法就是给这个对象添加Observer对象,然后在手动拼接处理。这种方法有一个问题就是,如果很多地方都需要这样处理,那岂不是要添加很多的Observer对象。此时,更好的办法就是通过map方法进行简单的转换:

    val mUserLiveData:MutableLiveData<User> = MutableLiveData()
    val mInfoLiveData:MutableLiveData<String> = map(mUserLiveData) { user->
         MutableLiveData(user.mName + " " + user.age)
    }
    

      上面是我随手写的伪代码,大家先凑合着吧。接下来我们来看一下map方法的实现:

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

      map方法最大的特点就是只支持静态转换。什么叫做静态转换,就是要想转换的LiveData对象已经确定,即已经初始化了。如果我们要想动态转换应该怎么办呢?那就是switchMap方法,这也是这两个方法最大的区别。

    (2). switchMap方法

      在了解switchMap方法之前,我们先来了解一下什么叫做动态转换吧。假设有两个LiveData,其中一个LiveData持有的userId,我们称之为mUserIdLiveData,一个LiveData持有的User,我们称之为mUserLiveData。当mUserIdLiveData发生了变化,我们想要的结果是mUserLiveData也随之发生变化。
    因为User要等请求回来,我们才知道具体的对象,所以此时map方法不适合此情形,那么用switchMap 应该怎么实现的呢?

    val mUserIdLiveData = MutableLiveData<String>()
    val mUserLiveData = switchMap(mUserIdLiveData){ userId -> 
        repository.loadUserById(userId)
    }
    

      整个过程是如此的:mUserIdLiveData的更新导致了User的更新,如果不通过switchMap方法,mUserLiveData 根本不能知道Id更新。
      接下来,我们再看看switchMap的实现:

        @MainThread
        public static <X, Y> LiveData<Y> switchMap(
                @NonNull LiveData<X> source,
                @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
            final MediatorLiveData<Y> result = new MediatorLiveData<>();
            result.addSource(source, new Observer<X>() {
                LiveData<Y> mSource;
    
                // (1)
                @Override
                public void onChanged(@Nullable X x) {
                    LiveData<Y> newLiveData = switchMapFunction.apply(x);
                    if (mSource == newLiveData) {
                        return;
                    }
                    if (mSource != null) {
                        result.removeSource(mSource);
                    }
                    mSource = newLiveData;
                    if (mSource != null) {
                        result.addSource(mSource, new Observer<Y>() {
                            // (2)
                            @Override
                            public void onChanged(@Nullable Y y) {
                                result.setValue(y);
                            }
                        });
                    }
                }
            });
            return result;
        }
    

      实现也是非常的简单,我结合上面的例子简单的解释一下。当mUserIdLiveData更新,(1)处方法会被调用,此时通过我们传递进去的Callback接口创建一个新的LiveData,然后在这个新的LiveData添加一个观察者,当这个新的LiveData数据请求回来,会回调(2)方法,此时result就被更新。如果我们给这个result对象设置了Observer观察者,我们就能监听到数据的更新。
      不得不说,switchMap方法设计真的太巧妙,短短几行代码就实现了效果。

    5. 总结

      到此为止,LiveData相关的介绍和分析也结束了。在这里,我对本文做一个简单的总结。

    1. LiveData通知Observer主要有两个路径:1. 通过setValue或者postValue,此路径对所有活跃的Observer都生效;2. 添加一个新的Observer,如果此时对应的组件处于活跃状态,那么该Observer的onChanged方法也会被回调,但是只有该Observer的onChanged方法被回调,并不会影响到其他Observer。
    2. MediatorLiveData可以merge多个LiveData源。内部是通过一个Source类实现,当某一个LiveData更新了,Source类将对应的更新作用到MediatorLiveData的Observer。
    3. map 和switchMap区别在于:map只支持静态转换,而switchMap同时支持静态转换和动态转换。同时map和switchMap内部都是用MediatorLiveData实现的。

    相关文章

      网友评论

          本文标题:Jetpack 源码分析(二) - LiveData源码分析

          本文链接:https://www.haomeiwen.com/subject/egzvmhtx.html