前言
消息总线又叫事件总线,**为什么我们需要一个消息总线呢?**是因为随着项目变大,页面变多,我们可能出现跨页面、跨组件、跨线程、跨进程传递消息与数据,为了更方便的直接通知到指定的页面实现具体的逻辑,我们需要消息总线来实现。
消息总线演变历程(BroadcastReceiver–>EventBus–>RxBus–>LiveDataBus–> FlowBus )
从最基本的 BroadcastReceiver 到 EventBus 再到RxBus ,后来官方出了AndroidX jetpack 我们开始使用LiveDataBus,最后到Kotlin的流行出来了FlowBus。我们看看他们是怎么一步一步演变的。
1、BroadcastReceiver
作为四大组件之一,网上很多教程都有说明,这里就不做过多的介绍
2、Eventbus的使用例子
简介:Eventbus
eventbus的目的,就是为了减少一些复杂的接口回调,使它们解耦或者组件间的通信,简单高效的对一下组件的通信和广播的优化,从而更清晰管理自己的项目需求,另一个是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息.优点是开销小,代码更优雅。以及将发送者和接收者解耦。
注意:
1、EventBus.getDefault().register(this); 放在初始化组件之前
(如: findViewById() ) ,一定放在它的后面,不然页面也会接收不到参数。
2、postSticky对消息进行存储,运行register就会收到,缓存数据;post只在已经register里面收到,不缓存数据
引入:
implementation 'org.greenrobot:eventbus:3.0.0'
源码
MainActivity :
class MainActivity : AppCompatActivity() {
@Subscribe
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
EventBus.getDefault().register(this)
//其实这一句就可以了,我这里是测试
val event = MessageEvent(1,"系统时间为::"+System.currentTimeMillis())
//post就是把消息发送出去
EventBus.getDefault().postSticky(event)//postSticky对消息进行存储,运行register就会收到,缓存数据,基本上都是用postSticky
//EventBus.getDefault().post(event)//post只在已经register的activity里面收到,不缓存数据
bt_1.setOnClickListener{
startActivity(Intent(this@MainActivity, Main2Activity::class.java))
}
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
}
Main2Activity:
class Main2Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main2)
EventBus.getDefault().register(this)
Log.d("WY+","运行到此处")
bt_2.setOnClickListener {
startActivity(Intent(this, Main3Activity::class.java))
}
}
/**
* @subscribe 注解必须要写,线程需要指定
* 方法名可随意
*/
@Subscribe(threadMode = ThreadMode.MAIN)
fun onmessageevent(messageEvent: MessageEvent) {
Log.d("WY+","==2收到了消息:"+messageEvent.message)
// when (event.message) {
//
// }// do your thing
}
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
fun Event(messageEvent: MessageEvent) {
Log.d("WY+","2收到了消息:"+messageEvent.message+"类型为:"+messageEvent.Type)
if(messageEvent.Type==1){
}
//移除粘性事件,加了这个代码后,跳到第三个activity就不会运行eventbus里面的事件了,如果不加,跳到第三个会运行收到消息
EventBus.getDefault().removeStickyEvent(messageEvent)//解决postSticky事件重复接收问题
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
}
Main3Activity:
class Main3Activity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main3)
EventBus.getDefault().register(this)
}
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
fun Event(messageEvent: MessageEvent) {
Log.d("WY+","3收到了消息:"+messageEvent.message)
}
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this)
}
}
MessageEvent类:
class MessageEvent(var Type:Int, var message: String?)
使用技巧:我们可以通过创建不同的AMessageEvent,BMessageEvent,来控制在哪里接收。在post和接收的地方都对应上才能收到。(具体可以参考朋友 在线app的使用)
最后,想看demo可以到这里下载:
https://download.csdn.net/download/wy313622821/12264709
3、LiveEventBus
导入依赖:
implementation 'io.github.jeremyliao:live-event-bus-x:1.8.0'
消息发送(字符串):
LiveEventBus.get<String>("some_key")
.post("我是消息内容-11");
消息接收(字符串):
LiveEventBus
.get("some_key", String::class.java)
.observe(this) {
Log.d("Main", "接收到的消息为:$it")
}
消息发送(自定义类):
//定义类型
class DemoEvent(val content: String) : LiveEvent
LiveEventBus.get<DemoEvent>("key2")
.post(DemoEvent("我是消息内容-222"))
消息接收(自定义类):
LiveEventBus
.get("key2", DemoEvent::class.java)
.observe(this) {
Log.d("Main", "==>接收到的消息为:${it.content}")
}
4、FlowBus的使用例子
FlowBus 代码
import android.util.Log
import androidx.lifecycle.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
/**
* FlowBus消息总线
*/
object FlowBus {
private const val TAG = "FlowBus"
private val busMap = mutableMapOf<String, EventBus<*>>()
private val busStickMap = mutableMapOf<String, StickEventBus<*>>()
@Synchronized
fun <T> with(key: String): EventBus<T> {
var eventBus = busMap[key]
if (eventBus == null) {
eventBus = EventBus<T>(key)
busMap[key] = eventBus
}
return eventBus as EventBus<T>
}
@Synchronized
fun <T> withStick(key: String): StickEventBus<T> {
var eventBus = busStickMap[key]
if (eventBus == null) {
eventBus = StickEventBus<T>(key)
busStickMap[key] = eventBus
}
return eventBus as StickEventBus<T>
}
//真正实现类
open class EventBus<T>(private val key: String) : LifecycleObserver {
//私有对象用于发送消息
private val _events: MutableSharedFlow<T> by lazy {
obtainEvent()
}
//暴露的公有对象用于接收消息
val events = _events.asSharedFlow()
open fun obtainEvent(): MutableSharedFlow<T> =
MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)
//主线程接收数据
fun register(lifecycleOwner: LifecycleOwner, action: (t: T) -> Unit) {
lifecycleOwner.lifecycle.addObserver(this)
lifecycleOwner.lifecycleScope.launch {
events.collect {
try {
action(it)
} catch (e: Exception) {
e.printStackTrace()
Log.e(TAG, "FlowBus - Error:$e")
}
}
}
}
//协程中发送数据
suspend fun post(event: T) {
_events.emit(event)
}
//主线程发送数据
fun post(scope: CoroutineScope, event: T) {
scope.launch {
_events.emit(event)
}
}
//自动销毁
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onDestroy() {
Log.w(TAG, "FlowBus - 自动onDestroy")
val subscriptCount = _events.subscriptionCount.value
if (subscriptCount <= 0)
busMap.remove(key)
}
}
class StickEventBus<T>(key: String) : EventBus<T>(key) {
override fun obtainEvent(): MutableSharedFlow<T> =
MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)
}
}
发送
FlowBus.with<String>("标识key").post(this.lifecycleScope,"我是消息")
接收
FlowBus.with<String>("标识key").register(this.viewLifecycleOwner){
Log.d("wang","收到消息为:"+it)
}
粘性消息
发送粘性消息
FlowBus.withStick<String>("test-key-02").post(lifecycleScope, "Test Stick Message")
接收
FlowBus.withStick<String>("test-key-02").register(this){
Log.w("==","收到粘性消息:$it")
}