美文网首页
Andorid-JetPack-基于LiveData封装事件总线

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

作者: 信仰年輕 | 来源:发表于2021-08-12 16:16 被阅读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组件用法和源码解析

    相关文章

      网友评论

          本文标题:Andorid-JetPack-基于LiveData封装事件总线

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