这周本来想再输出一篇vsomeip协议栈的服务提供流程源码分析的,无奈流程以及其中的状态太过于复杂,还在梳理中,于是准备水一篇应用内通讯组件EventBus来缓解一下疲累的心情(梳理源码的流程过于心累),之所以挑准了EventBus,是结合了实际工作过程中的场景:车机内部的进程间通信,以及应用内的组件通信的频率很高。准备后续就这方面来进行一些流程的优化开发,所以预先借助分析EventBus的使用方式,设计思想,以及源码实现来构造自己的通信组件SDK。
说了那么多废话,下面进入正题,看下官网上提供的一个通信架构图,EventBus采用的是一个观察者模式设计,事件发布者提交事件给到总线,总线再将事件分发给订阅者。
在工程模块的build.gradle文件中添加如下依赖配置:
dependencies {
implementation 'org.greenrobot:eventbus:3.3.1'
...
...
}
EventBus的源码量很少,API也很少,下面来分别来介绍下:
register(注册)
/**
* Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
* are no longer interested in receiving events.
*
* Subscribers have event handling methods that must be annotated by {@link Subscribe}.
* The {@link Subscribe} annotation also allows configuration like {@link
* ThreadMode} and priority.
*/
public void register(Object subscriber)
unregister(反注册)
/** Unregisters the given subscriber from all event classes. */
public synchronized void unregister(Object subscriber)
Subscribe(订阅方法注解)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
/**
* If true, delivers the most recent sticky event (posted with
* {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
*/
boolean sticky() default false;
/** Subscriber priority to influence the order of event delivery.
* Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
* others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
* delivery among subscribers with different {@link ThreadMode}s! */
int priority() default 0;
}
使用Activity来举个例子
class TestActivity : AppCompatActivity() {
override fun onStart() {
super.onStart()
//注册当前模块为监听器
EventBus.getDefault().register(this)
}
override fun onStop() {
super.onStop()
//解注册模块
EventBus.getDefault().unregister(this)
}
//定义监听回调方法,方法可见为全局的pulic方法,方法执行在Main函数中,优先级为1000,且监听的事件类型为粘性事件
@Subscribe(threadMode = ThreadMode.MAIN, priority = 1000, sticky = true)
fun eventObserver(event: Event1?){
Log.i("eventbus", "seconds Received: ${data1.v0}")
}
}
上述定义后,只要有其他模块提交数据类型为Data1的事件,eventObserver方法就会在主线程中被执行,我们就可以在函数中处理对应的数据; 当然我们也可以让eventObserver函数运行在子线程中,只需要改变注解中的threadMode值即可。EventBus是根据@SubScribe所注解的函数参数来查找该模块所监听的参数,如果模块需要监听总线上所有的数据,则修改函数入参的类型为Any(Java语言为Object), 如果需要监听某一类型的数据,则需要定义数据类型与子数据,然后修改入参即可。
data class Event0(val data0 : Int, val data1 : Int)
open class Event1(data0 : Int, data1 : Int)
class SubEvent(data0: Int, data1: Int, name:String = "SubEvent") : Event1(data0, data1)
class SubEvent1(data0: Int, data1: Int, data2:Int, name: String = "SubEvent") : Event1(data0, data1)
上述Demo中可以监听类型为Event1, SubEvent, SubEvent1的数据
/** Posts the given event to the event bus. */
public void post(Object event)
/**
* Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky
* event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}.
*/
public void postSticky(Object event)
演示代码:
private var i : Boolean = false
findViewById<Button>(R.id.post_data).setOnClickListener {
EventBus.getDefault().post(if(i) SubEvent(0,0) else SubEvent1(1,1, 1))
EventBus.getDefault().postSticky(if(i) SubEvent(0,0) else SubEvent1(1,1, 1))
i = i.not()
}
终止事件处理
/**
* Called from a subscriber's event handling method, further event delivery will be canceled. Subsequent
* subscribers
* won't receive the event. Events are usually canceled by higher priority subscribers (see
* {@link Subscribe#priority()}). Canceling is restricted to event handling methods running in posting thread
* {@link ThreadMode#POSTING}.
*/
public void cancelEventDelivery(Object event)
移除粘性事件
/**
* Remove and gets the recent sticky event for the given event type.
*
* @see #postSticky(Object)
*/
public <T> T removeStickyEvent(Class<T> eventType)
/**
* Removes the sticky event if it equals to the given event.
*
* @return true if the events matched and the sticky event was removed.
*/
public boolean removeStickyEvent(Object event)
/**
* Removes all sticky events.
*/
public void removeAllStickyEvents()
获取消息总线中的粘性事件
/**
* Gets the most recent sticky event for the given type.
*
* @see #postSticky(Object)
*/
public <T> T getStickyEvent(Class<T> eventType)
模块订阅状态
public synchronized boolean isRegistered(Object subscriber)
查找某事件类型是否有订阅模块
public boolean hasSubscriberForEvent(Class<?> eventClass)
回顾一下,在Android应用开发过程中,EventBus解决了Android应用开发过程中各个模块中通信问题,且内部提供了指定线程类型来处理事务的机制,让我们处理事件更加方便,事件类型与订阅者的类型不受限制,更加灵活。 但是它并不是完美的,就类似于注册与反注册这两步来说,如果开发者稍不注意,注册之后,没有调用反注册,那就一定会引起订阅模块的对象无法释放,进而造成内存泄漏等问题,所以我看现在有一个更新的替代方案:LiveDataBus,LiveDataBus结合了jetpack中组件的LifeCycle来规避了监听对象因生命周期而造成内存泄漏的问题,这个后续有空再写一篇聊聊。下一篇去看看EventBus源码,学习优秀的开源库,有利于身心健康。