基于APT的RxBus庫

在上篇文章我寫了一下基于RxJava2的RxBus簡單封裝,沒看過的同學可以簡單看下,我們可以看到對外暴露的注冊和解綁接口,用戶還需要在調用注冊方法后,手動管理RxJava2的Disposable或者CompositeDisposable對象,還是不是太方便開發者使用。那怎么改進呢?這里我借鑒EventBus這個開源庫的一些思想,通過Java Annotation Processing Tool (apt)生成輔助代碼來幫助用戶通過簡單的api就能實現消息總線的功能

Github

本項目已經放到Github上,歡迎興趣的同學fork查看示例和源碼,同時也歡迎star

目的

旨在App中使用Rxjava2的同學們可以方便通過這個庫,來使用類似于EventBus消息總線的功能,這樣就不用額外的引入EventBus,增加App的庫臃腫

引入

在你的Android Studio中module的build.gradle文件中引入

dependencies {
    annotationProcessor 'com.eggsy:rxbus-processor:0.0.4'
    compile 'com.eggsy:rxbus:0.0.4'
    // RxJava and RxAndroid is necessary
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
    compile 'io.reactivex.rxjava2:rxjava:2.0.4'
}

需要引入rxjava2rxandroid,如果你的App中沒有用到rxjava,那么不建議你使用RxBus庫,因為RxBus是基于rxjava2rxandroid,如果單純為了使用RxBus額外引入這兩個庫,我個人覺得是沒必要的,完全可以使用EventBus替換

如何使用

使用主要分為

  1. 注冊
  2. 注解事件方法
  3. 發出事件
  4. 解綁
注冊

在Activity,Fragment或者其他任何你的類中(比如Mvp模式中的Presenter
類),都可以用來注冊RxBus事件

RxBus.register(this); // 這里的this是指包含了下面注解事件方法的類實例
注解事件方法
@EventSubscribe
public void testboolean(boolean testParam) {  // boolean事件
    Toast.makeText(this, testParam, Toast.LENGTH_SHORT).show();
}

// tmode, 指定下面方法接收到事件之后,在哪個線程上運行
@EventSubscribe(tmode = ThreadMode.NewThread)
public void test(String testParam) {  // String類型事件
    Log.i(TAG,"test IoThread, main thread id="+getMainLooper().getThread().getId()+" , result="+testParam);
    Log.i(TAG,"test IoThread, curr thread id="+Thread.currentThread().getId()+" , result="+testParam);
    Toast.makeText(this, testParam, Toast.LENGTH_SHORT).show();
}

@EventSubscribe
public void testCustomEvent(TestEvent event) {  // 自定義事件
    Log.i(TAG, "test custom Event, event=" + event.toString());
}

這里的@EventSubscribe注解有兩個屬性

  1. tmode:指定事件發出時,注解的方法執行的線程,一共有6種模式
    • PostThread 與發出事件(調用RxBus.post()方法)所在線程使用同一個線程
    • MainThread 使用App主線程
    • IoThread 使用一個自增長的線程池中的線程,適合異步阻塞的IO操作
    • NewThread 使用一個新的線程
    • SingleThread 使用一個通用的單線程,支持用于主線程到其他線程的管道數據
    • ComputationThread 使用一個非主線程來做計算型的工作
  2. bpstrategy:指定上游事件發送很快,次數很多,注解方法來不及處理情況,這里指定一個策略,主要有6種策略
    • DEFAULT 如果不設置,默認該屬性,不做任何處理
    • MISSING 事件在沒有任何緩沖或丟棄的情況下寫入。注解方法需要處理所有任何溢出
    • ERROR 在注解方法處理速度不能跟上事件發出速度時,發出一個Exception
    • BUFFER 緩存事件,等到注解方法消費掉這個事件
    • DROP 如果注解方法不能跟上事件發送速度,丟棄最近的事件
    • LATEST 僅保留最新的事件,如果注解方法處理速度跟不上事件發出速度,則覆蓋任何先前的值,保留最新事件。

注意:注解方法限定了參數只能有一個,也就是指定接收一個事件觸發

發出事件
RxBus.post("eggsy test");  // 發出String類型的事件
RxBus.post(true);  // 發出boolean事件
RxBus.post(new Boolean(false));  // 發出Boolean類使勁
RxBus.post(newTestEvent(1,"post event object"));  // 當然,還可以發出自定義的對象事件

這里我支持發送的事件類型有兩種,一種是java 8種基礎類型以及包裝類,另外一種自定義類。其中,如果發出的事件類型是基礎類型,那么如果注解方法是對應包裝類型的事件,也會跟著觸發,反之,如果發出的是包裝類型的事件,那么注解方法是對應的基礎類型,也會跟著觸發,比如,發出如下事件

RxBus.post(true);  // 發出boolean事件
RxBus.post(new Boolean(false));  // 發出Boolean類使勁

那么下面方法會被觸發兩次

@EventSubscribe
public void testboolean(boolean testParam) {  // boolean事件
    Toast.makeText(this, testParam, Toast.LENGTH_SHORT).show();
}
解綁
 RxBus.unRegister(this);

在合適的地方,解綁注冊事件,這樣就收不到后續發出的事件,比如在Activity的onDestory中解綁,這樣就形成了一個完整的生命周期

生成輔助類

在編譯時,會生成一個_RxBusProxy后綴的輔助類,例如我例子中,

public class MainActivity_RxBusProxy implements RxBusProxy<MainActivity> {
    protected CompositeDisposable compositeDisposable;

    protected MainActivity sourceInstance;

    public CompositeDisposable register(MainActivity source) {
        sourceInstance = source;
        Disposable test4_disposable = RxBusHelper.getDefault().register(String.class, new Consumer<String>() {
            @Override
            public void accept(String o) throws Exception {
                sourceInstance.test4(o);
            }
        }, io.reactivex.schedulers.Schedulers.computation());
        if (compositeDisposable == null || compositeDisposable.isDisposed()) {
            compositeDisposable = new CompositeDisposable();
        }
        compositeDisposable.add(test4_disposable);
        return compositeDisposable;
    }

    public void unRegister() {
        if (compositeDisposable != null && !compositeDisposable.isDisposed()) {
            compositeDisposable.dispose();
        }
    }
}

栗子

具體栗子請參考我的github上的工程RxBus,歡迎大家fork下來玩玩。

總結

RxBus最基本的還是基于RxJava2RxAndroid,利用Rxjava2中的支持事件在不同線程之間傳遞,封裝出的一個類似于EventBus功能的庫,底層還是調用了我上一篇文章中的RxBus類,把事件與Rxjava2結合起來。然后利用Java APT,識別出@EventSubscribe注解和注解內容,動態的根據注解內容,生成注解方法所在類的一個輔助類,在輔助類里面做了register和unregister方法,實現注冊和解綁功能。對外封裝了api方便調用者根據傳入的類類型,找到對應的輔助類,調用register方法。

最后,謝謝大家查看這篇文章,寫的不好的或者有問題的,歡迎大家留言交流~~~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容