在上篇文章我寫了一下基于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'
}
需要引入rxjava2
和rxandroid
,如果你的App中沒有用到rxjava
,那么不建議你使用RxBus庫,因為RxBus是基于rxjava2
和rxandroid
,如果單純為了使用RxBus額外引入這兩個庫,我個人覺得是沒必要的,完全可以使用EventBus
替換
如何使用
使用主要分為
- 注冊
- 注解事件方法
- 發出事件
- 解綁
注冊
在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
注解有兩個屬性
-
tmode:指定事件發出時,注解的方法執行的線程,一共有6種模式
- PostThread 與發出事件(調用RxBus.post()方法)所在線程使用同一個線程
- MainThread 使用App主線程
- IoThread 使用一個自增長的線程池中的線程,適合異步阻塞的IO操作
- NewThread 使用一個新的線程
- SingleThread 使用一個通用的單線程,支持用于主線程到其他線程的管道數據
- ComputationThread 使用一個非主線程來做計算型的工作
-
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
最基本的還是基于RxJava2
和RxAndroid
,利用Rxjava2中的支持事件在不同線程之間傳遞,封裝出的一個類似于EventBus功能的庫,底層還是調用了我上一篇文章中的RxBus類,把事件與Rxjava2結合起來。然后利用Java APT,識別出@EventSubscribe注解和注解內容,動態的根據注解內容,生成注解方法所在類的一個輔助類,在輔助類里面做了register和unregister方法,實現注冊和解綁功能。對外封裝了api方便調用者根據傳入的類類型,找到對應的輔助類,調用register方法。
最后,謝謝大家查看這篇文章,寫的不好的或者有問題的,歡迎大家留言交流~~~