android——消息总线(Eventbus、FlowBus)

前言

消息总线又叫事件总线,**为什么我们需要一个消息总线呢?**是因为随着项目变大,页面变多,我们可能出现跨页面、跨组件、跨线程、跨进程传递消息与数据,为了更方便的直接通知到指定的页面实现具体的逻辑,我们需要消息总线来实现。

消息总线演变历程(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")
        }
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wy313622821

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值