Andorid-JetPack-基于LiveData封装事件总线

2021-08-12  本文已影响0人  信仰年輕

本文目标

基于LiveData组件封装,事件总线DataBus工具类

直接上代码

/**
 * Author: 信仰年轻
 * Date: 2021-01-19 13:40
 * Email: hydznsqk@163.com
 * Des:事件总线,基于LiveData
 */
object DataBus {

    private var mEventMap = ConcurrentHashMap<String, StickyLiveData<*>>()

    fun <T> with(eventName: String): StickyLiveData<T> {
        /**
         * 基于事件名称 订阅、分发消息,
         * 由于 一个 livedata 只能发送 一种数据类型
         * 所以 不同的event事件,需要使用不同的livedata实例 去分发
         */
        var liveData = mEventMap[eventName]
        if (liveData == null) {
            liveData = StickyLiveData<T>(eventName)
            mEventMap[eventName] = liveData
        }

        return liveData as StickyLiveData<T>
    }

    /**
     * 对LiveData的扩展,
     */
    class StickyLiveData<T>(private val eventName: String) : LiveData<T>() {

        internal var mStickyData: T? = null
        internal var mVersion = 0

        /**
         * 设置事件数据,就是在主线程去发送数据
         */
        fun setStickyData(stickyData: T) {
            this.mStickyData = stickyData
            setValue(stickyData)
        }

        /**
         * 设置事件数据,不受线程的限制
         */
        fun postStickyData(stickyData: T) {
            this.mStickyData = stickyData
            postValue(stickyData)
        }

        override fun setValue(value: T) {
            mVersion++
            super.setValue(value)
        }

        override fun postValue(value: T) {
            mVersion++
            super.postValue(value)
        }

        override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
            observerSticky(owner, false, observer)
        }

        /**
         * sticky:是否黏性 true:黏性 false:不黏性
         */
        fun observerSticky(owner: LifecycleOwner, sticky: Boolean, observer: Observer<in T>) {
            //允许指定注册的观察则 是否需要关心黏性事件
            //sticky =true, 如果之前存在已经发送的数据,那么这个observer会受到之前的黏性事件消息
            owner.lifecycle.addObserver(object : LifecycleEventObserver {
                override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                    //监听 宿主 发生销毁事件,主动把liveData 移除掉。
                    if (event == Lifecycle.Event.ON_DESTROY) {
                        mEventMap.remove(eventName)
                    }
                }
            })
            super.observe(owner, StickyObserver(this, sticky, observer))
        }
    }


    class StickyObserver<T>(
        val stickyLiveData: StickyLiveData<T>,
        val sticky: Boolean,
        val observer: Observer<in T>
    ) : Observer<T> {

        //lastVersion 和liveData的version 对齐的原因,就是为控制黏性事件的分发。
        //sticky 不等于true , 只能接收到注册之后发送的消息,如果要接收黏性事件,则sticky需要传递为true
        private var lastVersion = stickyLiveData.mVersion

        override fun onChanged(t: T) {
            if (lastVersion >= stickyLiveData.mVersion) {
                //就说明stickyLiveData  没有更新的数据需要发送。
                if (sticky && stickyLiveData.mStickyData != null) {
                    observer.onChanged(stickyLiveData.mStickyData)
                }
                return
            }

            lastVersion = stickyLiveData.mVersion
            observer.onChanged(t)
        }

    }
}

如何使用?

发送事件

DataBus.with<String>("login_success").postStickyData("登录成功了")

接受事件

//登录成功后收到事件来刷新列表
DataBus.with<String>("login_success").observerSticky(this,true, Observer {
    ......
})

总结

该工具类可以控制LiveData的黏性事件,所谓黏性事件,就是先发射事件,然后在注册,依然可以收到,我们可以只需要设置一个参数就能控制其是否要黏性
首先要明白为什么LiveData会有黏性事件,其实查看源码就知道,具体可以参考Andorid-JetPack-LiveData组件用法和源码解析

上一篇下一篇

猜你喜欢

热点阅读