轻量级EventBus(LightEventBus)介绍

一、前言

最近研究了一下项目上用的一个类EventBus框架,由于EventBus都在对象初始化的时候注册,导致启动非常耗时(注册是要遍历所有方法的),另外发现比较多消息处理的方法耗时非常长,导致后面的方法等待时间很长,而因为同一个业务包含了很多个模块,分属不同的部门负责,而这些模块共用一个EventBus,导致维护相当困难,所以花了几个小时,参考了相关框架,做了一个轻量级的EventBus框架,即LightEventBus,采用的懒遍历方式,即不在注册的时候遍历方法,同时引入分组的概念,可以按照业务分组或者组件分组,事件分发相互隔离,并且增加了请求-响应模型,当想要什么数据的时候,可以发送事件去请求数据,增加钩子,管理生命周期,即使不注销也不会出现内存泄露。因为考虑到异步会让框架比较大,做不到轻量,故暂不支持异步。

二、LightEventBus介绍

github地址:https://github.com/newhope1106/lighteventbus

下面引用github上的介绍

轻量级EventBus是什么

轻量级EventBus,即LightEventBus,主要面向业务单元或组件级别的通信框架,提出了分组的概念,具有以下特性:

1.特意设计成不支持异步,以业务单元划分或组件单元划分的常见通信,异步使用极少,而且异步会导致框架变得臃肿,这也就是轻量级的含义

2.支持组件级别的生命周期,也就是不需要在代码中手动注销,只需要通过钩子勾到组件里面,就可以和该组件生命周期一致

3.轻量级EventBus支持两种模式,发布-订阅模式,以及请求-响应模式,其中第二种是EventBus所没有的,另外发布-订阅模式的实现方式也和EventBus不太一样,效率更高

为什么要用轻量级EventBus

  1. EventBus面向的是大型业务级别场景,根据业务可以包含多个业务模块,如果多个业务模块接入的消息过多,会导致消息堵塞,举个例子,如果有1000个方法注册了同一个消息,处于同一个队列的情况,需要等前面的方法执行完成才能执行到自己,而方法本身是不知道要等这么长的,跨模块的方式也更会导致管理上的困难。LightEventBus则适合在业务单元或组件内使用,所见即所得,由业务单元或组件内来管理。(EvenBus虽然也支持单独实例化,但如果一个组件生成一个EventBus实例,岂不臃肿)
  2. EventBus的注册和注销是配套使用的,并且在注册时,就会遍历对象的所有方法,如果一启动就有非常多的对象需要监听,会严重影响性能,此外不注销会导致内存泄露,但有时注销不是那么方便的。LightEventBus虽然也需要调用注册接口,但真正的方法查找,只有等真正发送消息时才会去遍历,采用的是懒汉方式。另外可以不用调用注销方法,因为本身是和组件同生命周期的
  3. 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,谢谢百忙之中抽空阅读本篇博客!

发布了36 篇原创文章 · 获赞 11 · 访问量 6万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章