背景
在Android开发中数据传递的方式有很多种,常见的有
Intent在页面间传递数据
Handler刷新UI
Broadcast传递消息
系统提供的API在使用上会有些复杂。 举个示例:Handler发送数据并刷新UI
Handler mHandler = new Handler ( ) {
@Override
public void handleMessage ( Message msg) {
super . handleMessage ( msg) ;
switch ( msg. what) {
case 0 :
String data = ( String) msg. obj;
textView. setText ( data) ;
break ;
default :
break ;
}
}
} ;
private void getDataFromNet ( ) {
new Thread ( new Runnable ( ) {
@Override
public void run ( ) {
mHandler. sendEmptyMessage ( 0 ) ;
Message msg = new Message ( ) ;
msg. obj = "网络数据" ;
mHandler. sendMessage ( msg) ;
}
} ) . start ( ) ;
}
下面是EventBus简单使用的伪代码:
EventBus. getDefault ( ) . register ( this ) ;
EventBus. getDefault ( ) . unregister ( this ) ;
EventBus. getDefault ( ) . post ( new MessageEvent ( "Hello everyone!" ) ) ;
@Subscribe ( threadMode = ThreadMode. MAIN)
public void onMessageEvent ( MessageEvent event) {
Toast. makeText ( getActivity ( ) , event. message, Toast. LENGTH_SHORT) . show ( ) ;
}
当然,EventBus的出现不是为了取代系统API,只是给我们提供了更多的选择。 在系统API能轻松实现的情况下,就没必要引入EventBus了,虽然它只有60k。
接下来我们需要对EventBus进行更进一步的了解,才能更好地使用。
定义
EventBus GitHub 地址
EventBus 是一个事件发布/订阅轻量级框架。相关的发布订阅可参考:发布订阅-维基百科 。 关于观察者模式和发布订阅模式的谈论,可查看知乎这篇文章。 EventBus的事件发布者不会将事件直接发给订阅者,而是将发布的事件分为不同的类型,订阅者可以选择只感兴趣的事件订阅。 使用过EventBus的朋友回忆一下,确实是如此。没使用过EventBus的朋友可以耐心往下看。
它有以下优点:
能够简化组件间的通信
有效地将事件发送者和订阅者解耦
能避免复杂的依赖性和生命周期问题
在Fragment,Activity,Service, 后台线程之间传递数据,性能更好。
EventBus 可以代替Android传统的Intent,Handler,Broadcast 或接口函数,
基本使用
使用步骤分为下面几步:
引入依赖
定义事件对象
事件订阅和解除订阅
发送事件
引入依赖
implementation 'org.greenrobot:eventbus:3.1.1'
定义事件对象
public class MessageEvent {
public final String message;
public MessageEvent(String message) {
this.message = message;
}
}
事件订阅
事件不可重复订阅,一般我们在onCreate或者onStart方法中订阅
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
解除事件订阅
事件不可重复解除订阅,一般我们在onStop或者onDestory方法中解除订阅
@Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}
发送事件
普通事件:需要先注册事件才能接收到已发出的事件
粘性事件:事件不需要提前注册也能接收到。
比如:A 页面跳转 B 页面传递参数hello, 如果传递参数时使用粘性事件,也就是在A页面发送数据,在B页面注册事件。且接收粘性事件,那么B可以接收到参数hello 如果传递参数时使用普通事件,那么B可以接收不到参数hello。因为普通参数需要注册才能收到消息。
接下来看普通事件和粘性事件的使用。
普通事件
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
// 在主线程展示 Toast 结果
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show();
}
粘性事件
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
// 在主线程刷新 UI
@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent event) {
textField.setText(event.message);
}
// 移除粘性事件
MessageEvent stickyEvent = EventBus.getDefault().getStickyEvent(MessageEvent.class);
// Better check that an event was actually posted before
if(stickyEvent != null) {
// 移除某个事件
EventBus.getDefault().removeStickyEvent(stickyEvent);
// Now do something with it
}
// 移除全部事件
EventBus.getDefault().removeAllStickyEvents();
在接收数据时我们可以看到threadMode = ThreadMode.MAIN指定了线程环境,EventBus还提供了其他四种线程环境。
设置线程环境
ThreadMode.POSTING,This is the default,和发布者处在同一个线程,避免线程阻塞
ThreadMode.MAIN,UI 线程,避免线程阻塞
ThreadMode.MAIN_ORDERED,called in Android’s main thread,有顺序的订阅,避免线程阻塞
ThreadMode.BACKGROUND,called in a background thread. 单后台线程,也是需要避免线程阻塞
ThreadMode.ASYNC,called in a separate thread,使用场景,网络请求,内部使用线程池去维护
设置事件优先级
事件的优先级类似广播的优先级,优先级越高优先获得消息。默认优先级是0
//在 ui 线程执行 优先级 100
@Subscribe(threadMode = ThreadMode.MAIN, priority = 100)
public void onDataSynEvent(DataSynEvent event) {
Log.e(TAG, "event---->" + event.getCount());
}
总结
EventBus的基本使用还是很简单的,主要分为三步
注册事件需要和注销事件成对出现,否则会内存泄露。 而且注册事件要在onCreate或者onStart生命周期中注册,注销事件在onStop或者onDestory方法中。
发送事件分为普通事件和粘性事件。
普通事件只能在事件注册之后才能收到。
粘性事件能确保事件注册之后一定能接收到,粘性事件如果不需要了记得要移除。
粘性事件的移除又分为单个事件移除和全部事件移除。
END~
本文同步分享在 博客“_龙衣”(CSDN)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划 ”,欢迎正在阅读的你也加入,一起分享。