本文目标
基于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组件用法和源码解析
网友评论