注册

Android App封装 —— 实现自己的EventBus

背景


在项目中我们经常会遇到跨页面通信的需求,但传统的EventBus都有各自的缺点,如EventBus和RxBus需要自己管理生命周期,比较繁琐,基于LiveData的Bus切线程比较困难等。于是我参考了一些使用Flow实现EventBus的文章,结合自身需求,实现了极简的EventBus。


EventBus


image.png


EventBus是用于 Android 和 Java 的发布/订阅事件总线。Publisher可以将事件Event post给每一个订阅者Subscriber中接收,从而达到跨页面通信的需求。


可以看出EventBus本身就是一个生产者消费者模型,而在我们第一篇搭建MVI框架的时候,用到的Flow天然就支持生产者和消费者模型,所以我们可以自己用Flow搭建一个自己的EventBus


基于Flow搭建EventBus


根据EventBus的架构图,我们来用Flow搭建,需要定义一下几点



  1. 定义事件Event
  2. 发送者 Publisher 如何发送事件
  3. 如何存储Event并且分发
  4. 如何订阅事件

1. 定义事件


sealed class Event {
data class ShowInit(val msg: String) : Event()
}

这个和之前搭建MVI框架类似,用一个sleaed classdata class或者object来定义事件,用来传递信息


2. 发送事件


fun post(event: Event, delay: Long = 0) {
...
}

发送事件定义一个这样的函数就可以了,传入事件和延迟时间


3. 存储Event并且分发


对于同一种Event,我们可以用一个SharedFlow来存储,依次发送给订阅方。而在整个App中,我们会用到各种不同种类的Event,所以这时候我们就需要用到HashMap去存储这些Event了。数据结构如下:


private val flowEvents = ConcurrentHashMap<String, MutableSharedFlow<Event>>()

4. 订阅事件


inline fun <reified T : Event> observe(
lifecycleOwner: LifecycleOwner,
minState: Lifecycle.State = Lifecycle.State.CREATED,
dispatcher: CoroutineDispatcher = Dispatchers.Main,
crossinline onReceived: (T) -> Unit
)


  • lifecycleOwner,用来定义订阅者的生命周期,这样我们就不需要额外管理注册与反注册了
  • minState,定义执行订阅的生命周期State
  • dispatcher,定义执行所在的线程
  • onReceived,收到Event后执行的Lamda

使用


    //任何地方
FlowEventBus.post(Event.ShowInit("article init"))

// Activity或者Fragment中
FlowEventBus.observe<Event.ShowInit>(this, Lifecycle.State.STARTED) {
binding.button.text = it.msg
}

完整代码


object FlowEventBus {

//用HashMap存储SharedFlow
private val flowEvents = ConcurrentHashMap<String, MutableSharedFlow<Event>>()

//获取Flow,当相应Flow不存在时创建
fun getFlow(key: String): MutableSharedFlow<Event> {
return flowEvents[key] ?: MutableSharedFlow<Event>().also { flowEvents[key] = it }
}

// 发送事件
fun post(event: Event, delay: Long = 0) {
MainScope().launch {
delay(delay)
getFlow(event.javaClass.simpleName).emit(event)
}
}

// 订阅事件
inline fun <reified T : Event> observe(
lifecycleOwner: LifecycleOwner,
minState: Lifecycle.State = Lifecycle.State.CREATED,
dispatcher: CoroutineDispatcher = Dispatchers.Main,
crossinline onReceived: (T) -> Unit
) = lifecycleOwner.lifecycleScope.launch(dispatcher) {
getFlow(T::class.java.simpleName).collect {
lifecycleOwner.lifecycle.whenStateAtLeast(minState) {
if (it is T) onReceived(it)
}
}
}

}

作者:剑冲
链接:https://juejin.cn/post/7182399245859684412
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册