輕量級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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章