写点什么

Android- 面试 -Jetpack-LiveData- 你必须滴知道得知道的那些玩意儿

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

override fun onDestroy() {super.onDestroy()ds.dispose()}


如上所示:通过 compositeDisable 可以避免 Rxjava 发生内存泄漏。但是这种方法依赖于用户手动操作,容易忘记与出现问题。


但使用 LiveData 却不用担心这个问题,LiveData 订阅后,在页面销毁后可以自动取消订阅


class MutableLiveDataFragment : Fragment() {


private val changeObserver = Observer<String> { value ->value?.let { txt_fragment.text = it }}


override fun onAttach(context: Context?) {super.onAttach(context)getLiveDataA().observe(this, changeObserver)}// .. some other Fragment specific code ..}

为什么 LiveData 可以自动取消订阅?

如果一个 Observer 的生命周期处于 STARTED 或 RESUMED 状态,那么 LiveData 将认为这个 Observer 处于活跃状态.LiveData 仅通知活跃的 Observer 去更新 UI。非活跃状态的 Observer,即使订阅了 LiveData,也不会收到更新的通知。


结合一个实现了 LifecycleOwner 接口的对象,你能注册一个 Observer。这种结合关系使得当具有生命周期的对象的状态变为 DESTROYED 时,Observer 将被取消订阅。这对于活和片段尤其有用,因为它们可以安全地订阅 LiveData 对象,而不必担心内存泄漏 - 当活和片段生命周期为 DESTROYED 时,它们


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


立即会被取消订阅。

1.首先看看订阅时发生了什么

@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");if (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}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);}


观察者被存放到了 mObservers 之中,其中存放的是 LifecycleBoundObserver 类型接下来看看 LifecycleBoundObserver 类


class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {@NonNullfinal LifecycleOwner mOwner;


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


@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}


@Overridepublic void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver);return;}activeStateChanged(shouldBeActive());}


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


@Overridevoid detachObserver() {mOwner.getLifecycle().removeObserver(this);}}


当 Lifecycles 的 State 发生变化会回调 onStateChanged 方法,当 State 为 DESTROYED 是,则移除观察者 Observer。里面调用的是 LiveData 的 removeObserver 方法


@MainThreadpublic void removeObserver(@NonNull final Observer<? super T> observer) {assertMainThread("removeObserver");ObserverWrapper removed = mObservers.remove(observer);if (removed == null) {return;}removed.detachObserver();removed.activeStateChanged(false);}


当页面销毁时,在 mObservers 中 remove 了 observer,就这样完成了订阅的自动取消。

livedata 传相同的值会不会执行 onchanged 回调?

当我们给 liveData 设置 value 时,Observer 就会更新。但如果我们两次设置一样的 value,Observer 是否会更新?


首先看看 setValue 方法


@MainThreadprotected void setValue(T value) {assertMainThread("setValue");mVersion++;mData = value;dispatchingValue(null);}


其中最重要的是 mVersion 参数接下来看 dispatchingValue 方法


void dispatchingValue(@Nullable ObserverWrapper initiator) {....considerNotify(initiator);....}


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;observer.mObserver.onChanged((T) mData);}


到这里一目了然,只要 mVersion 是大于等于之前的值,就会回调 onChanged 方法,也就是说,不管值是否相同,只看 version 的值,也就是基本只有 int 到达最大值的时候才会导致 bug,2 的 31 次方-1,估计只有无聊的人才会写改这么多次值的代码了。

LiveDataBus 实现

为什么要使用 LiveData 来实现通信总线?

使用 LiveData 的理由

  • LiveData 具有的这种可观察性和生命周期感知的能力,使其非常适合作为 Android 通信总线的基础构件。

  • 使用者不用显示调用反注册方法。由于 LiveData 具有生命周期感知能力,所以 LiveDataBus 只需要调用注册回调方法,而不需要显示的调用反注册方法。这样带来的好处不仅可以编写更少的代码,而且可以完全杜绝其他通信总线类框架(如 EventBus、RxBus)忘记调用反注册所带来的内存泄漏的风险。

为什么要用 LiveDataBus 替代 EventBus 和 RxBus

  • LiveDataBus 的实现及其简单 相对 EventBus 复杂的实现,LiveDataBus 只需要一个类就可以实现。

  • LiveDataBus 可以减小 APK 包的大小 由于 LiveDataBus 只依赖 Android 官方 Android Architecture Components 组件的 LiveData,没有其他依赖,本身实现只有一个类。作为比较,EventBus JAR 包大小为 57kb,RxBus 依赖 RxJava 和 RxAndroid,其中 RxJava2 包大小 2.2MB,RxJava1 包大小 1.1MB,RxAndroid 包大小 9kb。使用 LiveDataBus 可以大大减小 APK 包的大小。

  • LiveDataBus 依赖方支持更好 LiveDataBus 只依赖 Android 官方 Android Architecture Components 组件的 LiveData,相比 RxBus 依赖的 RxJava 和 RxAndroid,依赖方支持更好。

  • LiveDataBus 具有生命周期感知 LiveDataBus 具有生命周期感知,在 Android 系统中使用调用者不需要调用反注册,相比 EventBus 和 RxBus 使用更为方便,并且没有内存泄漏风险。

LiveData 实现事件总线的坑

由于 LiveData 的粘性特性,用 LiveData 实现 LiveDataBus,订阅者会收到订阅之前发布的消息。对于一个消息总线来说,这是不可接受的。无论 EventBus 或者 RxBus,订阅方都不会收到订阅之前发出的消息。对于一个消息总线,LiveDataBus 必须要解决这个问题。

粘性消息的原因

当 LifeCircleOwner 的状态发生变化的时候,会调用 LiveData.ObserverWrapper 的 activeStateChanged 函数,如果这个时候 ObserverWrapper 的状态是 active,就会调用 LiveData 的 dispatchingValue。 前面分析过,最后会调用到 considerNotify 方法


private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android-面试-Jetpack-LiveData-你必须滴知道得知道的那些玩意儿