下午赶去公司解决了电台业务首次语音搜台后(用到服务,但只出一个独立的Activity,主界面并没有打开)不能听歌识曲的问题.
排查到最后,去识别的消息确实是发出去了,但是却没有收到,没有收到消息当然不会响应.最后,消息是通过EventBus.getDefault.post(xx)发出的,一定是发送和接收出现问题.
推测该问题是由于主界面还未创建,用于接收的EventBus还未注册,即发布者发了消息,但订阅者还未产生(一般消息的处理逻辑是先注册订阅,后接收),这样没有收到消息当然无法响应操作.
了解到,EventBus是支持发送黏性事件的。
粘性事件?
何为黏性事件呢?简单讲,就是在发送事件之后再订阅该事件也能收到该事件。Android中就有这样的实例,也就是Sticky Broadcast,即粘性广播。正常情况下如果发送者发送了某个广播,而接收者在这个广播发送后才注册自己的Receiver,这时接收者便无法接收到 刚才的广播,为此Android引入了StickyBroadcast,在广播发送结束后会保存刚刚发送的广播(Intent),这样当接收者注册完 Receiver后就可以接收到刚才已经发布的广播。这就使得我们可以预先处理一些事件,让有消费者时再把这些事件投递给消费者.
EventBus也提供了这样的功能,有所不同是EventBus会存储所有的Sticky事件,如果某个事件在不需要再存储则需要手动进行移除。用户通过Sticky的形式发布事件,而消费者也需要通过Sticky的形式进行注册,当然这种注册除了可以接收 Sticky事件之外和常规的注册功能是一样的,其他类型的事件也会被正常处理。
基本使用
发布和接收粘性事件一般有如下几步:
1、粘性事件的发布:
EventBus.getDefault().postSticky("RECOGNIZE_SONG");
2、粘性事件的接收
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void receiveSoundRecongnizedmsg(String insType) { if ("RECOGNIZE_SONG".equals(insType)) { soundRecognizeCtrl(); } }
剩下的操作就和普通事件一样注册和反注册即可.
手动获取和移除粘性事件(Getting and Removing sticky Events manually)
正如你之前看到的,最近发布的粘性事件在其新订阅者注册后将会自动传递给新订阅者。但有时可能更方便手动检查粘性事件。有时我们也需要移除粘性事件,以免它在传递下去。
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);if(stickyEvent != null) { EventBus.getDefault().removeStickyEvent(stickyEvent); //TODO}
removeStickyEvent 会返回之前持有的粘性事件。
于是,
MessageEvent stickyEvent = EventBus.getDefault().removeStickyEvent(MessageEvent.class);if(stickyEvent != null) { //TODO}
使用场景
我们要把一个Event发送到一个还没有初始化的Activity/Fragment,即尚未订阅事件。那么如果只是简单的post一个事件,那么是无法收到的,这时候,你需要用到粘性事件,它可以帮你解决这类问题.
小结
对于EventBus3.0来说,我还只是知道如何简单的使用,是知其然,不知其所以然,它是一个比较强大的事件总线库,后续会看下源码,慢慢分析一下,消息是如何发送和接收的.