一、前言
最近研究了一下项目上用的一个类EventBus框架,由于EventBus都在对象初始化的时候注册,导致启动非常耗时(注册是要遍历所有方法的),另外发现比较多消息处理的方法耗时非常长,导致后面的方法等待时间很长,而因为同一个业务包含了很多个模块,分属不同的部门负责,而这些模块共用一个EventBus,导致维护相当困难,所以花了几个小时,参考了相关框架,做了一个轻量级的EventBus框架,即LightEventBus,采用的懒遍历方式,即不在注册的时候遍历方法,同时引入分组的概念,可以按照业务分组或者组件分组,事件分发相互隔离,并且增加了请求-响应模型,当想要什么数据的时候,可以发送事件去请求数据,增加钩子,管理生命周期,即使不注销也不会出现内存泄露。因为考虑到异步会让框架比较大,做不到轻量,故暂不支持异步。
二、LightEventBus介绍
github地址:https://github.com/newhope1106/lighteventbus
下面引用github上的介绍
轻量级EventBus是什么
轻量级EventBus,即LightEventBus,主要面向业务单元或组件级别的通信框架,提出了分组的概念,具有以下特性:
1.特意设计成不支持异步,以业务单元划分或组件单元划分的常见通信,异步使用极少,而且异步会导致框架变得臃肿,这也就是轻量级的含义
2.支持组件级别的生命周期,也就是不需要在代码中手动注销,只需要通过钩子勾到组件里面,就可以和该组件生命周期一致
3.轻量级EventBus支持两种模式,发布-订阅模式,以及请求-响应模式,其中第二种是EventBus所没有的,另外发布-订阅模式的实现方式也和EventBus不太一样,效率更高
为什么要用轻量级EventBus
- EventBus面向的是大型业务级别场景,根据业务可以包含多个业务模块,如果多个业务模块接入的消息过多,会导致消息堵塞,举个例子,如果有1000个方法注册了同一个消息,处于同一个队列的情况,需要等前面的方法执行完成才能执行到自己,而方法本身是不知道要等这么长的,跨模块的方式也更会导致管理上的困难。LightEventBus则适合在业务单元或组件内使用,所见即所得,由业务单元或组件内来管理。(EvenBus虽然也支持单独实例化,但如果一个组件生成一个EventBus实例,岂不臃肿)
- EventBus的注册和注销是配套使用的,并且在注册时,就会遍历对象的所有方法,如果一启动就有非常多的对象需要监听,会严重影响性能,此外不注销会导致内存泄露,但有时注销不是那么方便的。LightEventBus虽然也需要调用注册接口,但真正的方法查找,只有等真正发送消息时才会去遍历,采用的是懒汉方式。另外可以不用调用注销方法,因为本身是和组件同生命周期的
- EventBus只支持发布-订阅模式,而且一个方法对应一个消息,但是LightEventBus则从另外一种角度来诠释,可以解决方法数限制的问题(方法个数不能超过65535),且方法调用效率更高(把消息作为Key值,而不是遍历所有方法),EventBus采用的是遍历方式查找方法,此外LightEventBus还支持请求-响应模式。
添加LightEventBus
gradle依赖
compile 'com.appleye.eventbus:LightEventBus:1.0.0'
或者
implementation 'com.appleye.eventbus:LightEventBus:1.0.0'
maven依赖
<dependency>
<groupId>com.appleye.eventbus</groupId>
<artifactId>LightEventBus</artifactId>
<version>1.0.0</version>
<type>pom</type>
</dependency>
LightEventBus架构简单示意图
三、LightEventBus使用
github源码里面有几种情况的例子,可以参考源码,下面简单介绍贴一下代码介绍如何使用
1.在build.gradle中增加依赖
implementation 'com.appleye.eventbus:LightEventBus:1.0.0'
2.定义分组
public class Constants {
public static final String GROUP_MAIN = "demo";
}
3.定义事件
public class EventApi {
//分发数据事件
public static final String EVENT_SAY_HELLO = "lightbus://say/hello";
//请求数据事件
public static final String EVENT_REQUEST_MSG = "lightbus/request/message";
}
4.注册订阅者、增加钩子、分发数据和请求数据、处理多事件、处理单事件
public class MainActivity extends AppCompatActivity {
@Hook
private IEventBus mEventBus;//钩子
//计数
private AtomicInteger mCounter = new AtomicInteger(0);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册订阅者,增加钩子
EventBusFac.getInstance(Constants.GROUP_MAIN).register(this).hook(this);
findViewById(R.id.hello_world_tv).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mEventBus != null) {
//请求数据(请求-响应模型)
Event requestEvent = new Event(EventApi.EVENT_REQUEST_MSG);
Response response = mEventBus.request(requestEvent);
if(response != null && Response.OK == response.resultCode) {
//分发数据(订阅发布模型)
Event event = new Event(EventApi.EVENT_SAY_HELLO);
event.data = response.body;
mEventBus.postEvent(event);
}
}
}
});
}
//处理多个事件
@Subscriber(eventType = {EventApi.EVENT_SAY_HELLO, EventApi.EVENT_REQUEST_MSG})
public void handleEvent(Event event) {
switch (event.type){
case EventApi.EVENT_SAY_HELLO:{
//处理分发数据事件
Toast.makeText(this, (String)event.data, Toast.LENGTH_SHORT).show();
break;
}
case EventApi.EVENT_REQUEST_MSG:{
//处理请求数据事件
if(mEventBus != null) {
mEventBus.response(event, "Hello World!!!");
}
break;
}
}
}
//处理单个事件
@Subscriber(eventType = {EventApi.EVENT_SAY_HELLO})
public void handleSayHelloEvent(Event event) {
if(EventApi.EVENT_SAY_HELLO.equals(event.type)){
((TextView)findViewById(R.id.count_tv)).setText(String.valueOf(mCounter.incrementAndGet()));
}
}
}
四、后续计划
后续会考虑看是否有简单的方式增加异步,并且还会增加性能埋点接口,欢迎所有人star、fork源码以及提交issue,谢谢百忙之中抽空阅读本篇博客!