EventBus的優雅封裝

Android機動車發表於2018-03-28

EventBus是一款針對Android優化的釋出/訂閱事件匯流排。可以替代廣播、startActivityForResult、Handler、非同步回撥等來實現各元件間、元件與後臺執行緒間的通訊。它的優點是開銷小,程式碼更優雅,以及將傳送者和接收者解耦。

通常我們在使用EventBus的時候都是直接需要接收通訊的Activity/Fragment中通過EventBus.getDefault().register(this)訂閱事件,在需要發起通訊的邏輯直接呼叫EventBus.getDefault().post(Object event)來發布事件。但是要是一個專案中有很多地方都使用EventBus來通訊,比如重新登入後更新各個頁面的登入狀態,或者是接收到通知更新訊息提示等,都這樣直接使用的話程式碼重複率很高,並且呢,如果以後升級或者更換EventBus時,各個地方都要修改,這就比較麻煩了。因此我一般是將EventBus的釋出和訂閱封裝到BaseActivity/BaseFragment中。

接下來我們開始封裝之路:

1、添依賴

在Gradle中新增EventBus依賴:

compile 'org.greenrobot:eventbus:3.0.0'
複製程式碼

2、考慮基類中進行繫結

2.1、我們應該這樣想,如果在BaseActivity或BaseFragment中定義一抽象方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (isRegisterEventBus()) {
        EventBusUtil.register(this);
    }
}

/**
 * 是否註冊事件分發
 *
 * @return true繫結EventBus事件分發,預設不繫結,子類需要繫結的話複寫此方法返回true.
 */
protected boolean isRegisterEventBus() {
    return false;
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (isRegisterEventBus()) {
        EventBusUtil.unregister(this);
    }
}
複製程式碼

如上,那豈不所有Base類的子類都需要去實現 isRegisterEventBus 方法,來返回是否繫結EventBus,那對於不繫結EventBus的類來說不是很累贅麻煩嘛。

2.2、使用註解

現在想想,使用註解是不是會方便一些呢?

先建立一註解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindEventBus {
}
複製程式碼

現在,只要被此註解修飾的類,就表示與EventBus繫結。那麼在Base類中:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 若使用BindEventBus註解,則繫結EventBus
    if(this.getClass().isAnnotationPresent(BindEventBus.class)){
        EventBusUtils.register(this);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // 若使用BindEventBus註解,則解繫結EventBus
    if(this.getClass().isAnnotationPresent(BindEventBus.class)){
        EventBusUtils.unregister(this);
    }
}
複製程式碼

這樣方便多了。

3、對Event的封裝

public class Event<T> {
    private int code;
    private T data;


    public Event(int code, T data) {
        this.code = code;
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}
複製程式碼

Event傳入一個泛型T,這裡T是具體的事件類,Event是將具體事件與對應業務code進行封裝。

再來看下code

public class EventCode {

    public static final int A = 0x111111;
    public static final int B = 0x222222;
    public static final int C = 0x333333;
    public static final int D = 0x444444;

}
複製程式碼

這裡可以定義一些業務相關的code,如登入、支付等等。以便將來對其分類處理。

4、處理類

public class EventBusUtils {

    /**
     * 繫結 接受者
     * @param subscriber
     */
    public static void register(Object subscriber) {
        EventBus.getDefault().register(subscriber);
    }

    /**
     * 解繫結
     * @param subscriber
     */
    public static void unregister(Object subscriber){
        EventBus.getDefault().unregister(subscriber);
    }

    /**
     * 傳送訊息(事件)
     * @param event
     */
    public static void sendEvent(Event event){
        EventBus.getDefault().post(event);
    }

    /**
     * 傳送 粘性 事件
     *
     * 粘性事件,在註冊之前便把事件發生出去,等到註冊之後便會收到最近傳送的粘性事件(必須匹配)
     * 注意:只會接收到最近傳送的一次粘性事件,之前的會接受不到。
     * @param event
     */
    public static void sendStickyEvent(Event event){
        EventBus.getDefault().postSticky(event);
    }
}
複製程式碼

前兩個方法是註冊也解註冊,已經在Base類中用到了。

sendEvent和sendStickyEvent就是具體的傳送訊息的方法,注意這裡傳送的是Event。

5、使用

5.1、Activity或Fragment中

@BindEventBus
public class ABCActivity extends BaseActivity {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void handleEvent(Event<ABC> event){
        // do something
    }
}
複製程式碼

繼承Base類,使用BindEventBus註解;

建立接收和處理事件的方法。

5.2、傳送訊息

Event<ABC> event=new Event<>(0,new ABC());
EventBusUtils.sendEvent(event);
複製程式碼

這樣就ok了。各位大神有好的建議就告訴我哦。

更多精彩內容,關注我的微信公眾號——Android機動車

這裡寫圖片描述

相關文章