40

LiveDataBus 的实现比你想象中的简单

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzIxNzU1Nzk3OQ%3D%3D&%3Bmid=2247490477&%3Bidx=1&%3Bsn=1db2058f08a9e47789d9fd53f8567648
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

code小生 一个专注大前端领域的技术平台 公众号回复 Android 加入安卓技术群

作者:BugRui

链接:https://www.jianshu.com/p/9b00422fbcc1

声明:本文已获 BugRui 授权发表,转发等请联系原作者授权

为什么要用LiveData实现事件总线呢?

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

LiveData 具有生命周期感知能力,确保界面符合数据状态,不会发生内存泄露,不会因 Activity停止而导致崩溃,不再需要手动处理生命周期,数据始终保持最新状态

LiveData 我就不多做介绍了,LiveData已经有很多,很详细的文章,接下来谈谈如何使用LiveData实现事件总线

使用LiveData实现事件总线的难点在于LiveData 为了在视图控制器发生重建后,能够 自动倒灌 所观察的 LiveData 的最后一次数据,LiveData 被设计为粘性事件,在此之前我看了很多关于LiveDataBus的文章,关于非粘性 LiveData 的实现,网上存在通过 “事件包装类”和 “反射干预 LastVersion” 两种方式来解决.

LiveDataBus的实现真的需要这么麻烦吗?不,我觉得不需要。

接下来分享一下 我的实现思路

定义一个HashMap用于保存不同的消息通道

private val liveDataMap = HashMap<String, MutableLiveData<Any?>>()

LiveData 为了在视图控制器发生重建后,能够 自动倒灌 所观察的 LiveData 的最后一次数据,LiveData 被设计为粘性事件的解决方案

解决方案:

为了避免收到重复的事件,这里我使用的解决方案是每次都new一个新的MutableLiveData替换原来的MutableLiveData,这样一来,每次配置更改的时候都会new一个新的MutableLiveData,也就不会收到上一个MutableLiveData的消息,但是多处订阅的时候只需要使用不同的tag,否则只有最后一个订阅的地方收到

 fun with(tag: String): LiveData<Any?>? {
     liveDataMap.put(tag,MutableLiveData())
     return liveDataMap[tag]
 }

订阅事件,仅更新处于活动生命周期状态的应用程序组件观察者

LiveDataBus.with(tag).observe(this, Observer {
         //收到消息
})

订阅的时候,observe仅更新处于活动生命周期状态的应用程序组件观察者,如果需要不受生命周期的影响,只要数据更新就会收到通知可以使用observeForever,这意味着给定的观察者将接收所有事件,并且永远不会被自动删除。需要手动调用removeObserver(Observer)来停止这个LiveData

/**
     * Adds the given observer to the observers list. This call is similar to
     * {@link LiveData#observe(LifecycleOwner, Observer)} with a LifecycleOwner, which
     * is always active. This means that the given observer will receive all events and will never
     * be automatically removed. You should manually call {@link #removeObserver(Observer)} to stop
     * observing this LiveData.
     * While LiveData has one of such observers, it will be considered
     * as active.
     * <p>
     * If the observer was already added with an owner to this LiveData, LiveData throws an
     * {@link IllegalArgumentException}.
     *
     * @param observer The observer that will receive the events
     */
    @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);
    }

使用observeForever 订阅,不受生命周期的影响,只要数据更新就会收到通知

LiveDataBus.with(tag).observeForever(this, Observer {
         //收到消息
})

事件的发送

fun send(tag: String, t: Any? = null) {
    if (!liveDataMap.containsKey(tag) ) return
    liveDataMap[tag]?.postValue(t)
}

// 发送
LiveDataBus.send(tag)

LiveDataBus 的源码可以直接拷贝使用,也可以前往作者的 GitHub 仓库查看下载: https://github.com/BugRui/LiveDataBus


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK