LiveData 深度解析

1,647 阅读19分钟

LiveData

可以被观察的数据持有类。

map 成员变量

1632759208(1).png

  • LiveData 内部持有一个Map类型的成员变量 mObservers:SafeIterableMap。key:Observer 保存的是原始的观察者对象,而 value:ObserverWrapper 保存的是由"原始的观察者对象"封装而成的包装类对象 ObserverWrapper 。
    • ObserverWrapper:该抽象类有两个实现类,LifecycleBoundObserver、AlwaysActiveObserver。
    • LifecycleBoundObserver:持有生命周期所有者 LifecycleOwner,其活跃状态与所有者相关。
    • AlwaysActiveObserver:没有与之关联的生命周期所有者,默认始终处于活跃状态。
  • 往 map 中添加数据 putIfAbsent():在调用 LiveData.observe()/observeForever() 方法注册观察者对象时,方法内部会分别构造不同的 ObserverWrapper 对象(LifecycleBoundObserver/AlwaysActiveObserver),并将该对象与原始的观察者对象 Observer 建立联系,然后添加到 map 中。
  • 从 map 中移除数据 remove():当调用 removeObserve() 方法移除观察者对象时,会根据传递的方法参数 Observer 观察者对象作为 key,移除对应的数据。

添加观察者

LiveData.observe(LifecycleOwner,Observer)

1632813755(1).png

  • observe():要求必须在主线程中被调用。需要两个方法参数,所有者对象、观察者对象。
  • 首先会判断所有者对象所关联的 Lifecycle 对象的当前状态 State,是否处于 Destroy 状态?如果是,则直接忽略。
  • 如果所有者不处于销毁状态,则会使用方法参数(所有者对象与观察者对象)去构造一个 LifecycleBoundObserver 对象,然后将其添加到 LiveData 的成员变量 mObservers:Map 中。
  • 【注意】此时还会将新建的对象 LifecycleBoundObserver 作为观察者,添加到所有者当中注册成为所有者的观察者对象,从而监听所有者对象生命周期的改变。当所有者的生命周期发生改变,LifecycleBoundObserver.onStateChanged() 方法会被回调,首先会去判断所有者所关联的 Lifecycle 对象是否处于 Destroy 状态?如果是,则直接调用 LiveData.removeObserver() 方法移除该观察者对象,从而避免内存泄漏。如果否,则会调用 activeStateChanged() 方法来更新当前观察者的活跃状态并触发数据更新。

LiveDate.observeForver(Observer)

1632815231(1).png

  • observeForever():要求必须在主线程中被调用。需要一个方法参数,观察者对象。
  • 直接使用方法参数(观察者对象)去构造一个 AlwaysActiveObserver 对象,然后将其添加到 LiveData 的成员变量 mObservers:Map 中。
  • 【注意】添加完毕之后,会直接调用新建对象 AlwaysActiveObserver.activeStateChanged() 方法并将参数设置为true,直接将观察者对象切换到活跃状态;AlwaysActiveObserver 默认会一直处于活跃状态。

移除观察者

removeObserve()

1632816019(1).png

  • removeObserve():要求必须在主线程中被调用。需要一个方法参数 Observer,原始的观察者对象。
    • ① 从 LiveData 的成员变量 mObservers:Map 中移除方法参数所对应的数据,并获得其所对应的包装类对象 ObserverWrapper。
    • ② 调用 ObserverWrapper.detachObserver() 取消关联,并调用其 activeStateChanged() 并置为 false,标记当前观察者对象为非活跃状态。

区分:ob 与 obForever()

需要区分 observe() 与 observeForever()。

  • observe():与所有者的生命周期相关联,持有 LifecycleOwner 所有者对象。
    • 原始的观察者对象 Observer,对应的 ObserverWrapper 对象为 LifecycleBoundObserver 类型。
    • 在持有的所有者对象被销毁(切换到Destroy状态)时,会自动调用 removeObserver() 方法自动移除观察者对象,从而避免内存泄漏。
    • 由此可知,通过 observer() 方法添加的观察者对象,无须手动进行移除,当组件被销毁时会自动移除观察者对象。
  • observeForever():在没有关联的所有者对象的情况下注册一个观察者对象。
    • 原始的观察者对象 Observer,对应的 ObserverWrapper 对象为 AlwaysActiveObserver 类型。
    • 由于没有与之关联的生命周期所有者,且该观察者对象默认一直处于活跃状态,因此必须在组件销毁时手动调用 LiveData.removeObserver() 方法主动移除观察者对象,否则会导致内存泄漏。

ObserverWrapper

1632759899(1).png

  • 成员变量 mActive,该标记位用于表示“当前观察者对象是否处于活跃状态”;在 activeStateChanged(boolean) 方法中被更新。
  • 抽象方法 shouldBeActive():Boolean,返回值表示“当前观察者对象是否处于活跃状态”。
    • LifecycleBoundObserver:返回其所持有的 LifecycleOwner 所有者对象所关联的 Lifecycle 对象是否处于活跃状态(根据其 currentState 进行判断)。
    • AlwaysActiveObserver:直接返回 true。
  • 持有一个成员变量 mObserver:Observer 观察者对象,该对象保存的是“原始的观察者对象”。
    • 当 LiveData 所持有的数据发生改动时,会遍历其成员变量 mObservers:Map,获取到对应的 ObserverWrapper 对象,然后调用其所持有的原始的观察者对象 Observer.onChanged() 方法进行回调。从而实现将数据分发给观察者对象。
  • 持有一个成员变量 mLastVersion:Int ,用于标记当前的数据版本 version。
    • 当 LiveData 持有的数据改动时,会优先根据该变量来判断当前观察者对象是否已经更新到最新版本的数据?如果不是最新版本的数据,才会去通知对应的观察者对象。
  • 在通知观察者对象时,① 更新为当前持有数据的最新版本号,即更新成员变量 mLastVersion;② 调用原始的观察者对象的 onChanged() 方法进行数据分发

LifecycleBoundObserver

当调用 LiveData.observe(LifecycleOwner,Observer) 时,会使用方法参数(所有者对象与观察者对象)去构造一个 LifecycleBoundObserver 对象, 然后将其添加到成员变量 mObservers:Map 中。

1632760499(1).png

  • 持有一个成员变量 mOwner:LifecycleOwner 所有者对象
    • 根据该对象所关联的 Lifecycle 对象的 currentState,从而判断当前观察者对象是否处于活跃状态。
  • 当调用 LiveData.observe(LifecycleOwner,Observer) 方法,该方法内会构造并将新建的 LifecycleBoundObserver 对象添加到map中,最后会获取该方法参数 LifecycleOwner 所有者对象所关联的 Lifecycle 对象并调用其 addObserver() 方法,将新建的 LifecycleBoundObserver 对象添加为该所有者的观察者对象,从而监听到所有者的生命周期的改变。而移除监听的实现是通过重写 ObserverWrapper.detachObserver() 方法并在该方法中移除监听(当 LiveData.removeObserver() 方法被调用时会回调该方法)。
    • LifecycleBoundObserver 不仅实现了 ObserverWrapper 抽象类,也实现了 LifecycleEventObserver 接口,从而能够监听到所有者的生命周期的改变。
    • 因此,当所有者的生命周期发生改变,同样会回调 onStateChanged() 方法。
  • onStateChanged()
    • 首先会判断当前持有的所有者所关联的 Lifecycle 对象是否处于 Destroy 状态?如果是,则直接调用 LiveData.removeObserver() 方法移除该观察者对象,从而避免内存泄漏。
    • 如果否,则会调用 activeStateChanged() 方法来更新当前观察者的活跃状态并触发数据更新。

AlwaysActiveObserver

当调用 LiveData.observeForver(Observer) 时,会使用方法参数(观察者对象)去构造一个 AlwaysActiveObserver 对象,然后将其添加到成员变量 mObservers:Map 中。

1632764242(1).png

  • AlwaysActiveObserver 实现了 ObserverWrapper 抽象类,重写了抽象方法 shouldBeActive() 并直接返回了 true。表示该观察者对象一直处于活跃状态。
  • AlwaysActiveObserver 没有与之关联的所有者 LifecycleOwner,不会监听到生命周期的改变,因此无法自动移除。使用时,必须在组件销毁的时候手动调用 LiveData.removeObserver(Observer)的方法主动移除观察者对象,避免内存泄漏。

ObserverWrapper.activeStateChanged()

更新当前的活跃状态,且在观察者对象切换至活跃状态时触发数据更新。

1632798655(1).png

  • 该方法的主要操作:① 调用 LiveData.changeActiveCounter() 方法更新"观察者对象的活跃数量"【详见】。② 当观察者对象切换至活跃状态时,会调用 LiveData.dispatchingValue() 触发数据分发
  • 该方法的方法参数 newActivie,表示最新的活跃状态。
  • 对于 LifecycleBoundObserver 来说
    • 当其所持有的 LifecycleOwner 所有者对象的生命周期发生改变,则会调用该方法来更新观察者对象的活跃状态,此时方法参数为 shouldBeActive() 方法的返回值。
    • 置为 false 的时机有两个:① 调用 LiveData.removeObserver() 移除观察者对象时 ② 数据更新时,该观察者对象所持有的 LifecycleOwner 所有者对象所关联的 Lifecycle 对象处于非活跃状态,即 shouldBeActive() 返回 false 时。
  • 对于 AlwaysActiveObserver 来说
    • 当调用 observeForever() 方法,构造并将新建的 AlwaysActiveObserver 对象添加到map之后,会直接调用该新建对象的 AlwaysActiveObserver.activeStateChanged() 方法,并将参数置为 true。
    • 置为 false 的时机有且只有一个:① 调用 LiveData.removeObserver() 移除观察者对象时。
  • 综上,对于 AlwaysActiveObserver 来说,观察者对象会永远处于活跃状态,除非主动调用 LiveData.removeObserver() 方法移除观察者;而对于 LifecycleBoundObserver 对象来说,观察者对象是否处于活跃状态 与 其所持有的所有者对象的生命周期的状态 是相关联的,并且会在所有者对象被销毁时自动移除该观察者对象

数据分发

将数据更新or最新的数据,分发给观察者对象。

LiveData.dispatchingValue()

1632799038(1).png

  • 调用时机1:ObserverWrapper.activeStateChanged(),当观察者对象切换至活跃状态时,触发数据分发。此时方法参数不为空。
    • 使用该方法参数作为参数对象,调用 considerNotify() 方法。
  • 调用时机2:LiveData.setValue(),主动更新数据时,触发数据分发。此时方法参数为空。
    • 遍历 LiveData 持有的成员变量 mObservers:Map ,获取到对应的 ObserverWrapper 对象,然后依次调用 considerNotify() 方法。
  • 由此可知,最终都会去到 considerNotify() 进行处理。

LiveData.considerNotify()

真正分发数据更新的地方。 此处会调用原始观察者对象 Observer.onChanged() 方法进行数据分发。

1632804022(1).png

  • 首先会判断调用方法参数 ObserverWrapper.shouldBeActive() 方法,从而判断观察者对象是否处于活跃状态?如果不是处于活跃状态,则不处理。如果处于活跃状态,才会进行数据的处理。从而实现【只更新处于活跃状态的观察者对象
    • 由上述可知,对于 AlwaysActiveObserver 对象来说,该方法永远返回 true。而对于 LifecycleBoundObserver 对象来说,会根据其所持有的所有者对象所关联的 Lifecycle 的当前状态 currentState 进行判断。
  • 当观察者对象被判断为“处于活跃状态”时,则优先判断方法参数 ObserverWrapper 对象的最新数据版本号是否已经为最新版本?如果是,则不处理;否则则进行数据分发操作。
    • ① 更新 ObserverWrapper 对象的最新数据版本号;
    • ② 获取 ObserverWrapper 对象中持有的原始的观察者对象 Observer,并调用其 onChanged() 方法分发数据,从而将最新的数据通知观察者对象。

数据更新

更新当前 LiveData 存储的最新数据。

setValue()

1632805519(1).png

  • setValue() 方法:要求必须在主线程中被调用。
    • 会判断当前是否在主线程?如果不是在主线程调用,则会抛异常。
    • 也就是说,调用 setValue() 方法必须在主线程调用。
    • 通过 LiveData 的静态方法 assertMainThread(),判断当前是否在主线程。
    • 该方法最终通过调用 ArchTaskExecutor 来进行判断处理【详见】。
  • 数据更新操作处理:① mVersion 版本号+1,② 替换数据 mData,③ 调用 dispatchingValue() 来分发数据更新从而通知观察者对象。
    • 由于此时传递的参数为空 null,因此会遍历 LiveData 持有的成员变量 mObservers:Map 对象,获取到对应的包装类对象 ObserverWrapper,然后依次调用 considerNotify() 方法。
    • considerNotify() 方法最终就是通过获取原始的观察者对象 Observer,并调用其 onChanged() 方法从而将最新的数据 mData 作为参数传递给观察者对象。从而完整了整个观察者模式。

postValue()

1632809301(1).png

  • postValue() 方法,通过 ArchTaskExecutor 直接 post 一个 Runnable 到主线程去做处理。【详见
  • mPostValueRunnable.run() 方法会在主线程中被执行。该方法内,直接调用 setValue() 并使用最新的数据作为参数进行传递。
    • 1632811884(1).png

小结-数据更新

  • 由此可知,setValue() 是用于在主线程调用以更新数据,而 postValue() 可用于非主线程中调用。postValue() 实际上只是往主线程里面post了一个Runnable,最终也是在主线程中去更新数据,在主线程中调用setValue()方法。
  • setValue()、postValue(),这两个方法在 LiveData 中是不公开的,也就是说 LiveData 对象无法调用这两个方法来更新持有的数据。在需要更新数据的场景中,不应使用 LiveData,应该使用 MutableLiveData,该子类重写并公开了 setValue()、postValue() 方法。

MutableLiveData

1632826040(1).png

LiveData.changeActiveCounter()

该方法的调用时机,是在 ObserverWrapper.activeStateChanged() 方法中。 当观察者对象处于活跃状态时,方法参数为 1;否则为 -1.

1632819904(1).png

  • 根据方法参数(+1、-1)去更改成员变量 mActiveCount:Int。该变量用于表示“当前 LiveData 对象持有多少处于活跃状态的观察者对象的数量”。
  • 更新完后,会根据上一个值以及最新值,判断当前"是否从0到1"以及"是否从1到0",从而仍决定是否需要回调 onActive()、onInactive()。
    • 当“活跃的观察者对象数量从0到1”,则会回调 LiveData.onActive() 方法
    • 当“活跃的观察者对象数量从1到0”,则会回调 LiveData.onInactive() 方法
    • 这两个方法默认为空实现。

ArchTaskExecutor

1632810399(1).png

  • 单例类,在 LiveData 中主要用于以下场景:
    • 场景1:判断当前是否位于主线程?① setValue() ② observe() ③ observeForever() ④ removeObserver() ⑤ removeObservers()
    • 场景2:调用 postValue() 方法去更新数据,此时需要 post 一个 Runnable 到主线程去执行数据更新的操作。
  • 采用了策略模式,该类持有一个真正执行操作的代理对象 mDelegate,其默认实现为 DefaultTaskExecutor。
    • 所有的操作都会转交给 mDelegate 成员变量进行处理。
    • 可通过调用 setDelegate() 方法注入不同的实现。

DefaultTaskExecutor.isMainThread()

1632811753(1).png

DefaultTaskExecutor.postToMainThread(Runnable)

1632812139(1).png

  • 调用成员变量 mMainHandler.post() 方法,将 Runnable 提交到主线程中进行处理。
  • mMainHandler 的构造:获取主线程的 Looper 对象,构造一个 Handler 对象并返回;因此,通过 mMainHandler 对象 post 的 Runnable,会在主线程中被处理。

1632812182(1).png

Observer

观察者对象。

1632825507(1).png

Observer.onChaged()

  • 当数据发生变更或者观察者对象切换到活跃状态,需要进行数据分发时,LiveData.considerNotify() 方法中就是通过获取并调用原始的观察者对象 Observer.onChanged() 方法,将最新数据传递给观察者对象。从而完整了整个观察者模式。

MediatorLiveData

LiveData 的子类。 可以合并多个 LiveData 源;只要任何源 LiveData 对象发生了改变,都会触发 MediatorLiveData 对象的观察者。

1632894025(1).png

  • 持有一个Map类型的成员变量 mSources:key 为 LiveData 类型,value 为 Source 类型。
    • 当调用 addSource() 方法添加 LiveData 源时,会使用方法参数(LiveData、Observer)构造并往 map 中添加一个 Source 对象。
    • 当调用 removeSource() 方法移除 LiveData 源时,会使用方法参数(LiveData)作为 key,从 map 中移除其所对应的 Source 对象。
  • 有一个私有静态内部类 Source。

Source

1632895643.png

  • 构造函数:需要传递两个参数,一个是 LiveData,一个是 Observer 。保存为成员变量。
  • Source 实现了 Observer 接口,本身可作为观察者来使用。
    • 提供了两个公开函数,支持往当前所持有的成员变量 mLiveData:LiveData 对象去添加-plug()、移除-unplug() 自己这个观察者对象。
    • 当持有的成员变量 mLiveData:LiveData 对象数据发生改变,Source.onChanged() 方法会被回调;Source.onChanged() 方法中会调用成员变量 mObserver.onChanged() 从而将数据更新分发给原始的观察者对象。
  • 需要注意的是,添加观察者对象使用的是 observeForever() 的方式,因此必须在组件销毁时主动调用 unplug() 方法从而移除观察者对象。

MediatorLiveData.addSource()

1632897029(1).png

  • 调用 addSource() 方法添加 LiveData 源时,会使用方法参数(LiveData、Observer)构造并往 map 中添加一个 Source 对象。
  • 添加完之后会调用 hasActiveObservers() 方法判断“当前 MediatorLiveData 是否有活跃的观察者对象”?如果有,则会调用新建的 Source 对象的 plug() 方法。
  • 上述可知,Source.plugn() 方法会往其所持有的成员变量 mLiveData:LiveData 对象添加自己为观察者对象,即往 LiveData 源添加自己为观察者对象去观察 LiveData 源的数据更新;当 LiveData 源数据发生变更时,Source.onChanged() 方法会被回调,此时就会调用其所持有的成员变量 mObserver:Observer 对象的 onChanged() 方法,从而将最新数据传递给原始的观察者对象。
  • 细节:同一个 LiveData 只能对应同一个 Observer 对象,否则 addSource() 添加 LiveData 源时会直接 crash 。

MediatorLiveData.removeSource()

1632898601(1).png

  • 调用 removeSource() 方法移除 LiveData 源时,会使用方法参数(LiveData)作为 key,从 map 中移除其所对应的 Source 对象。
  • 移除完之后,会调用被移除的 Source 对象的 unplug() 方法。
  • 上述可知,Source.unplug() 方法会让其所持有的成员变量 mLiveData:LiveData 移除自己这个观察者对象,即不再监听 LiveData 源的数据变更,从而避免内存泄漏。

小结-MediatorLiveData

  • MediatorLiveData,通过调用 addSource(LiveData,Observer) 方法添加 LiveData 源,那么当 LiveData 源发生数据变更时,LiveData 源所对应的 Observer 对象会接收到通知。
    • 这是因为:addSource() 会使用方法参数(LiveData、Observer)构造一个 Source 对象并添加到 map 中,然后会判断当前 MediatorLiveData 对象是否有活跃的观察者对象?如果有,就会调用该新建对象 Source.plug() 方法,该方法会为 LiveData 源添加自己作为观察者对象,从而监听 LiveData 数据的变更。
    • 当 LiveData 源数据发生变更,那么 Source.onChanged() 方法就会调用原始的观察者对象 Observer.onChanged() 方法将最新数据分发出去。
  • 当为 MediatorLiveData 添加多个 LiveData 源时,会为每个 LiveData-Observer 对去构造一个 Source 对象然后添加到 map 中。
  • MediatorLiveData 的使用:
    • ① 调用 MediatorLiveData.addSource(LiveData,Observer) 为其添加多个不同的 LiveData 源。
    • ② 在每个 LiveData 源所对应的 Observer 对象的 onChanged() 回调方法中,可接收到的最新数据值并进行处理,最后需要调用 MediatorLiveData.setValue()/postValue() 方法对其进行数据更新。由此实现,当每一个相关联的 LiveData 源更新时,都各自主动更新与之关联的 MediatorLiveData 对象。
    • ③ 通过对 MediatorLiveData 添加观察者对象,那么当 MediatorLiveData 数据发生更新时,就能收到最新的数据。从而实现,每一个相关联的 LiveData 源更新时,MediatorLiveData 都能接收到数据更新,【只要任何源 LiveData 对象发生了改变,都会触发 MediatorLiveData 对象的观察者】。

应用1:Transformations

用于转换LiveData。

Transformations.map()

1632909439(1).png

Transformations.switchMap()

d7ebe50339107a98ef96ccbb3e217fe.png

应用2:CoroutineLiveData


问题集锦

observer() VS observerForver()

  • 通过 observeForever() 方法添加的观察者对象,其包装类对象为 AlwaysActiveObserver。
    • observerForver() 方法会使用方法参数(观察者对象)去构造一个 AlwaysActiveObserver 对象,然后将其添加到 LiveData 的成员变量 mObservers:Map 中。
    • AlwaysActiveObserver 没有与之关联的生命周期所有者对象,即没有与任何组件的生命周期相关联,也不会去监听任何组件的生命周期的改变,默认始终处于活跃状态,其 shouldBeActive() 方法永远返回 true。
  • 通过 observe() 方法添加的观察者对象,其包装类对象为 LifecycleBoundObserver。
    • observer() 方法使用方法参数(生命周期所有者对象与观察者对象)去构造一个 LifecycleBoundObserver 对象,然后将其添加到 LiveData 的成员变量 mObservers:Map 中。
    • LifecycleBoundObserver 有与之关联的生命周期所有者对象,其活跃状态会与生命周期所有者的生命周期状态相关联。LifecycleBoundObserve.shouldBeActive() 方法,会根据其所关联的生命周期所有者对象 LifecycleOwner 的生命周期状态 currentState 进行判断。如果 currentState 为 START、RESUMED,则认为该观察者对象处于一个活跃状态;否则即为非活跃状态。

具有生命周期感知能力?

  • 当调用 LiveData.observer() 注册观察者对象时,会将新建的包装类对象 LifecycleBoundObserver:LifecycleEventObserver 作为生命周期观察者对象,添加到生命周期所有者当中从而实现对组件的生命周期状态的监听。LifecycleBoundObserve 实现了 LifecycleEventObserver 接口从而在 onStateChanged() 回调方法中接收到组件的生命周期状态的改变。
  • 当组件的生命周期发生改变,LifecycleBoundObserver.onStateChanged() 方法会被回调。该方法首先会去判断所有者对象 LifecycleOwner -即组件是否处于 Destroy 状态?如果是,则直接调用 LiveData.removeObserver() 方法移除观察者对象,从而避免内存泄漏。如果否,则会调用 shouldBeActive() 方法判断包装对象当前是否处于活跃状态,然后作为参数去调用 ObserverWrapper.activeStateChanged(boolean) 方法来更新包装对象的活跃状态并触发数据更新。
    • 如果 shouldBeActive() 方法返回 true,表示处于活跃状态,则会调用 LiveData.dispatchingValue() 方法去进行数据分发,将最近的数据分发给包装对象中所持有的原始的观察者对象 Observer.onChanged() 从而将最近的数据分发给该观察者对象。
    • 如果 shouldBeActive() 方法返回 false,则不进行分发操作。
  • 这里需要注意的是,当 LifecycleBoundObserver 关联的生命周期所有者对象 LifecycleOwner 处于非活跃状态但不是 Destroy 状态时,LiveData 并不会将该观察者对象从 LiveData.map 中移除;只有当组件处于 Destroy 状态时才会自动移除观察者对象。
    • 若在观察者处于非活跃状态期间,LiveData 的数据有更新时会进行数据分,此时 LiveData 通过遍历其成员变量 map 对所有注册了监听的观察者对象进行处理。首先会判断观察者对象所对应的包装类对象是否处于活跃状态?调用 ObserverWrapper.shouldBeActive() 方法。如果不是处于活跃状态,则不处理,即不会将最新的数据 mData 传递给观察者对象。
    • 之后,当组件从非活跃状态恢复到活跃状态时,LifecycleBoundObserver.onStateChanged() 方法会被回调。如果此时,所有者 LifecycleOwner -即组件,不处于Destroy 状态 且 处于活跃状态(即包装类对象处于活跃状态 shouldBeActive() 返回 true),则会调用 LiveData.dispatchingValue() 方法进行数据分发,将最近的数据分发给包装对象中所持有的原始的观察者对象 Observer.onChanged() 从而将最近的数据分发给该观察者对象。
    • 从而实现,当组件从非活跃状态恢复到活跃状态时,仍然会接收到 LiveData 关联的最新数据。
  • 由此可知,通过 observer() 方法添加的观察者对象无须手动进行移除,当组件被销毁时(即所有者对象切换至 Destroy 状态时),会自动从 LiveData 中移除观察者对象,从而避免内存泄漏;而通过 observeForever() 方法添加的观察者对象会一直处于活跃状态,因此会一直接收到数据更新,所以必须在组件销毁时手动调用 LiveData.removeObserver() 方法主动从 LiveData 中移除观察者对象,否则会导致内存泄漏。