基于RxJava2的RxBus2. 主要用于发送事件/订阅事件.类似EventBus. 支持Kotlin
欢迎访问我的GitHub地址:https://github.com/wind0ws/rxbus2
源码和使用示例都在上面。欢迎star和fork以及PR.
目前版本:V1.1.1, JavaDoc 文档:请点这里查看
特点
- 支持注解方式订阅事件。
- 支持粘滞事件。
- 支持3种Bus:
- Publish Bus( RxBus,参见 PublishSubject )
- Behavior Bus(参见 BehaviorSubject)
- Replay Bus(参见ReplaySubject)
集成
在项目的gradle中配置
allprojects {
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
}
在要集成RxBus2的模块的gradle中配置
implementation group: 'io.reactivex.rxjava2', name: 'rxjava', version: '2.x.x'
implementation('com.jakewharton.rxrelay2:rxrelay:2.0.0'){
exclude group: 'io.reactivex.rxjava2',module: 'rxjava'
}
implementation "com.github.wind0ws:rxbus2:1.1.1"
请将上面的2.x.x改成最新版本。截止到目前,最新的RxJava2版本是2.1.8
如果你的AndroidStudio是2.x版本,那么你需要把implementation
关键词换成compile
如果对配置gradle有任何疑问,请参见项目的gradle文件
配置(可选)
RxBus2是个纯粹的Java库,这意味着并没有集成与Android有关的任何东西,就像RxJava.
所以,如果在Android中使用注解(RxSubscribe)在主线程(UI线程)上处理订阅的事件,那么你需要配置一下RxBus 的主线程 Scheduler.配置很简单,在Application的onCreate()方法里写一句话即可。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
RxBus.setMainScheduler(AndroidSchedulers.mainThread());
}
}
AndroidSchedulers是RxAndroid库里的内容。
如果AndroidStudio提示找不到AndroidSchedulers,请记得先在gradle中引入RxAndroid
使用
这里以常用的RxBus(ReplayBus、BehaviorBus同理)为例。
这里先解释下什么是订阅粘滞事件和订阅普通事件:
- 订阅普通事件:只有建立订阅关系后发出的 事件 才能收到。
- 订阅粘滞事件:在建立订阅关系前发出的 粘滞事件 也能收到。
如果还有不明白的,建议看看Android里的 粘滞广播 和 普通广播.
注意事件本身不区分是普通的还是粘滞的,你只需要在发事件的时候告诉RxBus你发的事件是普通的还是粘滞的。
- 发事件:
发普通事件:post(event)
发粘滞事件:postSticky(event)
- 订阅事件:
订阅普通事件:ofType(String.class)
订阅粘滞事件:ofStickyType(String.class)
对于粘滞事件,还有一些高级用法,比如移除某个粘滞事件,清除某种类型的粘滞事件,清除所有粘滞事件等。这些可以去RxBus中查看源码和文档。
1. 手动订阅/解除订阅
手动订阅的记得要在合适的地方解除订阅哦!
比如在Android Activity里,在onDestroy里解除订阅关系,否则会发生内存泄露(也就是对象无法释放。)
@Override
protected void onDestroy() {
// manual listen event should release by yourself.
if (mCompositeDisposable != null) {
mCompositeDisposable.clear();
}
super.onDestroy();
}
首先在类里创建一个对象:
CompositeDisposable mCompositeDisposable = new CompositeDisposable();
- 订阅普通事件
Disposable subscribe =
RxBus.getDefault()
.ofType(String.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
String text = "{ [" + tag + "]:" + s+" }";
Log.d("RxBus”,text);
}
});
mCompositeDisposable.add(subscribe);//管理订阅对象,方便释放
RxBus.getDefault().post("Normal Event");
日志输出 Normal Event
- 订阅粘滞事件
RxBus.getInstance().postSticky("Sticky Event");
Disposable subscribe =
RxBus.getDefault()
.ofStickyType(String.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
String text = "{ [" + tag + "]:" + s+" }";
Log.d("RxBus”,text);
}
});
mCompositeDisposable.add(subscribe);//管理订阅对象,方便释放
RxBus.getDefault().post("Normal Event");
日志输出 Sticky Event ,Normal Event
2. 注解方式订阅
- 编写订阅事件方法
方法名随意,但是方法里有且仅有一个参数!方法可以为public,也可以用private修饰。 - 订阅普通事件
@RxSubscribe(observeOnThread = EventThread.MAIN)
public void listenRxIntegerEvent(int code) {
String text = String.format("{ Receive event: %s\nCurrent thread: %s }", code, Thread.currentThread());
Log.d("RxBus",text)
}
- 订阅粘滞事件
@RxSubscribe(observeOnThread = EventThread.IO,isSticky = true)
private void listenRxStringEvent(String event) {
final String text = String.format("{ Receive event: %s\nCurrent thread: %s }", event, Thread.currentThread());
Log.d("RxBus",text);
}
- 注册和取消注册订阅事件.
- 注册:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rx_bus);
RxBus.getDefault().register(this);
}
- 取消注册:
@Override
protected void onDestroy() {
super.onDestroy();
//auto release register with Annotation RxSubscribe.
RxBus.getDefault().unregister(this);
}
这里要说明一下,RxBus支持注解方式订阅和粘滞事件。BehaviorBus和ReplayBus都是不支持的(仅支持手动订阅和发普通事件。为什么不支持注解呢,因为这两种并不常(我)用(懒)。至于不支持粘滞事件,那是因为这两个天生不合适(这是真的). 比如对于ReplayBus, 他发的每个事件就是粘滞事件(因为每个订阅者不管什么时候订阅都能获取到订阅前的所有事件))。
想必理解三种Bus特点的同学估计已经知道原因了。不明白的请看看PublishSubject、BehaviorSubject、ReplaySubject的不同点: 参见这里
混淆与常见问题
- 如果使用注解(
@RxSubscribe
),那么请注意在progurad-rules.pro中加入混淆规则,以防release版注解被混淆
# For using annotation
-keepattributes *Annotation*
-keepattributes RuntimeVisibleAnnotations
-keepattributes RuntimeInvisibleAnnotations
-keepattributes RuntimeVisibleParameterAnnotations
-keepattributes RuntimeInvisibleParameterAnnotations
-keepclassmembers class ** {
@com.threshold.rxbus2.annotation.RxSubscribe ;
}
-keep enum com.threshold.rxbus2.util.EventThread { *; }
- 对于
Failed resolution of: Lcom/jakewharton/rxrelay2/PublishRelay
和Didn't find class "com.jakewharton.rxrelay2.PublishRelay"
这样的错误,肯定是在模块的build.gradle
的没有集成com.jakewharton.rxrelay2:rxrelay
09-24 22:52:37.531 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.threshold.learningdriving, PID: 1677
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/jakewharton/rxrelay2/PublishRelay;
at com.threshold.rxbus2.RxBus.(RxBus.java:79)
at com.threshold.rxbus2.RxBus.getDefault(RxBus.java:63)
at com.threshold.rxbus2.RxBus.getInstance(RxBus.java:51)
at com.threshold.learningdriving.ui.activity.LoginActivity.initRxBusEvent(LoginActivity.java:125)
at com.threshold.learningdriving.ui.activity.LoginActivity.onResume(LoginActivity.java:148)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
at android.app.Activity.performResume(Activity.java:6783)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3406)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3469)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.jakewharton.rxrelay2.PublishRelay" on path: DexPathList[[zip file "/data/app/com.threshold.learningdriving-1/base.apk"],nativeLibraryDirectories=[/data/app/com.threshold.learningdriving-1/lib/x86, /data/app/com.threshold.learningdriving-1/base.apk!/lib/x86, /system/lib, /vendor/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
at com.threshold.rxbus2.RxBus.(RxBus.java:79)
at com.threshold.rxbus2.RxBus.getDefault(RxBus.java:63)
at com.threshold.rxbus2.RxBus.getInstance(RxBus.java:51)
at com.threshold.learningdriving.ui.activity.LoginActivity.initRxBusEvent(LoginActivity.java:125)
at com.threshold.learningdriving.ui.activity.LoginActivity.onResume(LoginActivity.java:148)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1269)
at android.app.Activity.performResume(Activity.java:6783)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3406)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3469)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2732)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
如果还有什么不明白的,请先查看demo看看源码再来留言询问。