EventBus优缺点:
优点:简化组件之间的通信方式,实现解耦让业务代码更加简洁,可以动态设置事件处理线程以及优先级
缺点:目前发现唯一的缺点就是类似之前策略模式一样的诟病,每个事件都必须自定义一个事件类,造成事件类太多,无形中加大了维护成本
概述:
EventBus是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息。简化了应用程序内各组件间、组件与后台线程间的通信。优点是开销小,代码更优雅。以及将发送者和接收者解耦。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。
EventBus 三个主要的元素:
Event:事件。可以是任意类型的对象
Subscriber:事件订阅者onEvent,onEventMainThread,onEventBackgroundThread,
onEventAsync ,EventBus 3.0 函数名字不再受到权限
Publisher:事件发布者,可以在任意线程任意位置发送事件
关于ThreadMode:
onEvent: 如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
onEventMainThread: 如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
onEventBackground:如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
onEventAsync:使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync。
- NAIN UI主线程
- BACKGROUND 后台线程
- POSTING 和发布者处在同一个线程
- ASYNC 异步线程
基本用法:
- 引入EventBus:
compile 'org.greenrobot:eventbus:3.0.0'
- 定义事件:
public class MessageEvent { /* Additional fields if needed */ }
注册事件接收者:
eventBus.register(this);
发送事件:
eventBus.post(event)
- 接收消息并处理:
public void onEvent(MessageEvent event) {}
- 终止事件往下传递
EventBus.getDefault().cancelEventDelivery(event) ;//优先级高的订阅者可以终止事件往下传递
- 注销事件接收:
eventBus.unregister(this);
- 混淆
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
- 最后,proguard 需要做一些额外处理:
#EventBus
-keepclassmembers class ** {
public void onEvent*(**);
void onEvent*(**);
}
EventBus的粘性事件:
通俗讲是当前页把一个Event发送到一个还没有初始化的Activity/Fragment,即尚未订阅事件。那么如果只是简单的post一个事件,那么是无法收到的,这时候,你需要用到粘性事件,它可以帮你解决这类问题.
- 粘性事件的发布:
EventBus.getDefault().postSticky("RECOGNIZE_SONG");
- 粘性事件的接收
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void receiveSoundRecongnizedmsg(String insType) {
if ("RECOGNIZE_SONG".equals(insType)) {
soundRecognizeCtrl();
}
}
注意项
-
同一个onEvent函数不能被注册两次,所以不能在一个类中注册同时还在父类中注册。
-
消息的接收是根据参数中的类名来决定执行哪一个接收处理方法的。即:订阅者的处理方法是根据订阅事件的类型来确定订阅函数的。
-
每个事件可以有多个订阅者。
-
当Post一个事件时,这个事件类的父类的事件也会被Post。
-
所有事件处理方法必需是public void类型的,并且只有一个参数表示EventType。
EventBus 3.0 与2.x的区别
EventBus 2.x 必须定义以onEvent开头的几个方法,代码中语境比较突兀,且有可能会导致拼写错误,例如数据同步事件
EventBus 3.0 函数名字不再受到权限,而且可以在一个函数中体现出在哪个线程执行,并且可指定接收事件的优先级
EventBus 2.x 注册方式也比较繁琐
EventBus 3.0 注册方式只有一个
EventBus 3.0 性能更优
EventBus 2.x 是采用反射的方式对整个注册的类的所有方法进行扫描来完成注册,当然会有性能上的影响。EventBus 3.0中EventBus提供了EventBusAnnotationProcessor注解处理器来在编译期通过读取@Subscribe()注解并解析、处理其中所包含的信息,然后生成java类来保存所有订阅者关于订阅的信息,这样就比在运行时使用反射来获得这些订阅者的信息速度要快
出现接收不到事件的情况这边遇到过两种情况:
1 在使用Eventbus.getDefault().post(任意事件类型)方法的时候,必须是在注册事件(EventBus.getDefault().register(this);)之后发送事件才可以接收到,否则会出现接收不到的情况,也就是说在发送事件之前,此事件必须已经注册;
针对此问题解决办法:可以使用粘性事件 就是在发送事件的时候使用Eventbus.getDefault().postSticky(),就可以不用关心注册事件是否已经注册;或者注册前后的问题,如果发送粘性事件之前没有入注册事件,事件注册完成就会收到之前发送的粘性事件;
2 接受事件的方法参数事件类型必须为引用数据类型(不能为基本数据类型)例如当中的接收事件的方法
isPay(Boolean payResult) 方法参数(事件类型)必须为引用数据类型
3 区分不同的事件
EventBus是根据不同的类来区分事件发到哪离去
总结 参考来源
3.0源码分析
今天的文章Eventbus收录分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/59565.html