Android EventBus 简化应用程序组件(Activity、Fragment、线程)间通信的开源项目
2014-11-27 19:36
627 查看
项目地址:https://github.com/greenrobot/EventBus/
项目使用的技术呢,说白了,就是将要传递的event(一个Object对象,可任意自定义),发送到公共的组件EventBus中进行存储,
在通过EventBus传递给订阅者(使用者),订阅者收到event消息,就可以自行处理了。
不要被标题迷惑了,其实在任何地方 都可以发送和接收event(event,是一个通称,表示任意的数据对象,是一个消息类型)。
当然有需要注意的地方了,往下看吧。
分析一个基本的使用流程:
1. 自定义一个event类型:需要什么样的数据,就定义成什么样,随意了
2. 确定在哪里来接收该event,就在哪里调用EventBus.getDefault().register()进行订阅者的注册。
EventBus 一看就是个单例类,所以通过它存储、发送event。
可以在要处理事件的地方注册和接收;在发送事件的地方直接调用post(event)
register()有多个重载方法:
看名字也很好理解,subscriber即订阅者(接收处理event的类);priority即优先级,表示优先处理;
sticky粘性的意思,在源码中会有一个map对象,来存储sticky的event,
因为map的key是onEvent...()方法的第一个参数类型,
一般呢,这第一个参数就是订阅者对象,所以map会存储该类型的最后一次发送的event对象。
这些register都会最终调用一个私有register方法实现的,在这个方法里有个参数是SubscriberMethod对象。
调用subscriberMethod.findSubscriberMethods(), 查找到订阅者定义的接收处理event的方法,
并在EventBus中存起来。
3. 在订阅者中定义接收处理event的方法,约定为:
onEvent、onEventMainThread、onEventBackgroundThread、onEventAsync
使用时类似这样的:public void onEvent(Object event)。 onEvent对应PostThread,其他各自对应ThreadMode中的其他定义。
onEvent后面跟的这些名称的意义,见ThreadMode
4. 发送事件
调用EventBus.getDefault().post(Object event),发送事件
源码中会调用postToSubscription(),发送event给对应的订阅者方法
ThreadMode
这是一个枚举类。定义了四种类型:PostThread、MainThread、BackgroundThread、Async
PostThread 事件event的处理和发送都在相同线程中
MainThread 事件event的处理在主线程中,小心ANR
BackgroundThread 事件event的处理在后台线程(非主线程)中,它是阻塞式的,如有多个事件发送过来,会一个一个处理
Async 事件event的处理是异步的,即新开一个线程进行处理。
对应的接收事件方法:
PostThread
---- onEvent() 在发送事件的线程中接收事件
MainThread ---- onEventMainThread() 在主线程中接收
BackgroundThread ---- onEventBackgroundThread 在后台线程中接收
Async ---- onEventAsync 在异步线程中接收
例:在activity2中post(event),在activity1中注册为订阅者 并 接收事件 onEvent。 要在哪种类型线程中接收 ,参考上面的说明
使用注意:
1. 在register(Object subscription) 注册的subscription对象中 定义onEvent... 方法,至少需要定义一种
2. 如果所有的onEvent... 方法都注册 那么 都将收到消息(内部机制就是反射判断有哪些方法,从消息队列中取event)
3. onEvent(event) 所接收到的消息的数据类型任意(随你的意),在任意位置使用post(event)发送事件
4. 实际使用时,异步操作选用onEventAsync,主界面操作选用onEventMainThread
5. 在代码混淆时,注意保留onEvent... 方法
----------------------------------------------------------------------------------------------------分隔线-----------------------------------------------------------------------------------
实际工作中,我把该组件用于,跨activity、fragment等通知,即只要不是在同一个class文件中,需要通知交互的地方,就可以使用它
使用流程
> 定义一个事件类, class EventBean;在里面定义每种通知事件的常量类型。这样对于不需要传参的通知是够用了
> 在EventBean中,定义一个属性:Object data; 用于存储任意参数类型
> 如果当前在A-Fragment中,需要传一个 List<User> users; 给MainActivity,对users排序
在fragment中,发消息通知时大概是这样的:
在MainActivity中
—————————————————————2016-04-26——————————————————————
用Android Studio 加载了EventBus的Library;发现已经升级到3.0了,用法有变化:
主要是订阅(接收)事件消息的方法上,需要一个注解,这个比较麻烦
订阅事件的方法随意命名(即不用像老版本一样,必须使用约定的方法名),只要在方法上加一个注解
使用如下:
注解中的属性,都有默认值的:
threadMode 表示在哪个线程中接收消息
sticky 如果为true,表示收到粘性事件;相应的在发送事件时,要使用postSticky(Object event);
priority 优先级,值越大,越先处理
关于sticky,EventBus类中源码:
源码中的stickyEvents是一个Map类型。由此可见,多次postSticky同一类型后,
由getStickyEvent(class),可以拿到最新的该类型对象
其它方法:
eventbus.removeAllStickyEvents(); //删除所有粘性事件
eventbus.cancelEventDelivery(Object event); //取消事件提供(发送)
项目使用的技术呢,说白了,就是将要传递的event(一个Object对象,可任意自定义),发送到公共的组件EventBus中进行存储,
在通过EventBus传递给订阅者(使用者),订阅者收到event消息,就可以自行处理了。
不要被标题迷惑了,其实在任何地方 都可以发送和接收event(event,是一个通称,表示任意的数据对象,是一个消息类型)。
当然有需要注意的地方了,往下看吧。
分析一个基本的使用流程:
1. 自定义一个event类型:需要什么样的数据,就定义成什么样,随意了
2. 确定在哪里来接收该event,就在哪里调用EventBus.getDefault().register()进行订阅者的注册。
EventBus 一看就是个单例类,所以通过它存储、发送event。
可以在要处理事件的地方注册和接收;在发送事件的地方直接调用post(event)
register()有多个重载方法:
public void register(Object subscriber) { register(subscriber, false, 0); } public void register(Object subscriber, int priority) { register(subscriber, false, priority); } public void registerSticky(Object subscriber) { register(subscriber, true, 0); } public void registerSticky(Object subscriber, int priority) { register(subscriber, true, priority); } private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) { ... }
看名字也很好理解,subscriber即订阅者(接收处理event的类);priority即优先级,表示优先处理;
sticky粘性的意思,在源码中会有一个map对象,来存储sticky的event,
因为map的key是onEvent...()方法的第一个参数类型,
一般呢,这第一个参数就是订阅者对象,所以map会存储该类型的最后一次发送的event对象。
这些register都会最终调用一个私有register方法实现的,在这个方法里有个参数是SubscriberMethod对象。
调用subscriberMethod.findSubscriberMethods(), 查找到订阅者定义的接收处理event的方法,
并在EventBus中存起来。
3. 在订阅者中定义接收处理event的方法,约定为:
onEvent、onEventMainThread、onEventBackgroundThread、onEventAsync
使用时类似这样的:public void onEvent(Object event)。 onEvent对应PostThread,其他各自对应ThreadMode中的其他定义。
onEvent后面跟的这些名称的意义,见ThreadMode
4. 发送事件
调用EventBus.getDefault().post(Object event),发送事件
源码中会调用postToSubscription(),发送event给对应的订阅者方法
ThreadMode
这是一个枚举类。定义了四种类型:PostThread、MainThread、BackgroundThread、Async
PostThread 事件event的处理和发送都在相同线程中
MainThread 事件event的处理在主线程中,小心ANR
BackgroundThread 事件event的处理在后台线程(非主线程)中,它是阻塞式的,如有多个事件发送过来,会一个一个处理
Async 事件event的处理是异步的,即新开一个线程进行处理。
对应的接收事件方法:
PostThread
---- onEvent() 在发送事件的线程中接收事件
MainThread ---- onEventMainThread() 在主线程中接收
BackgroundThread ---- onEventBackgroundThread 在后台线程中接收
Async ---- onEventAsync 在异步线程中接收
例:在activity2中post(event),在activity1中注册为订阅者 并 接收事件 onEvent。 要在哪种类型线程中接收 ,参考上面的说明
public class EventBusActivity1 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EventBus.getDefault().register(this); //注册接收器 } //两个activity中使用eventBus public void eventBusEventWith2Acti(View view) {//onClick方法 startActivity(new Intent(this, EventBusActivity2.class)); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } public void onEvent(Object event) { //接收方法 在发关事件的线程接收 Looper.prepare(); Toast.makeText(this, "recevie a event:" + event + Thread.currentThread().getName(), Toast.LENGTH_SHORT).show(); Looper.loop(); } } public class EventBusActivity2 extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new Thread() { @Override public void run() { EventBus.getDefault().post(this.getClass().getSimpleName() + " 发了一个消息"); } }.start(); finish(); } }
使用注意:
1. 在register(Object subscription) 注册的subscription对象中 定义onEvent... 方法,至少需要定义一种
2. 如果所有的onEvent... 方法都注册 那么 都将收到消息(内部机制就是反射判断有哪些方法,从消息队列中取event)
3. onEvent(event) 所接收到的消息的数据类型任意(随你的意),在任意位置使用post(event)发送事件
4. 实际使用时,异步操作选用onEventAsync,主界面操作选用onEventMainThread
5. 在代码混淆时,注意保留onEvent... 方法
----------------------------------------------------------------------------------------------------分隔线-----------------------------------------------------------------------------------
实际工作中,我把该组件用于,跨activity、fragment等通知,即只要不是在同一个class文件中,需要通知交互的地方,就可以使用它
使用流程
> 定义一个事件类, class EventBean;在里面定义每种通知事件的常量类型。这样对于不需要传参的通知是够用了
> 在EventBean中,定义一个属性:Object data; 用于存储任意参数类型
> 如果当前在A-Fragment中,需要传一个 List<User> users; 给MainActivity,对users排序
/** * @Description: 管理所有跨界面消息通知事件 * @author aa86799@163.com */ public class EventBean { private int mEvent; private Object mData; /**主界面 对User 集合排序*/ public static final int EVENT_MAINACTIVITY_SORT_USER = 1; public EventBean() { } public EventBean(int event) { this.mEvent = event; } public EventBean(int event, Object data) { this(event); this.mData = data; } public int getEvent() { return this.mEvent; } public void setEvent(int event) { this.mEvent = event; } public Object getData() { return mData; } public void setData(Object data) { this.mData = data; } }
在fragment中,发消息通知时大概是这样的:
EventBus.getDefault().post(new EventBean(EventBean.EVENT_MAINACTIVITY_SORT_USER, users));
在MainActivity中
@Override public void onEventMainThread(EventBean event) { //在主线程中接收 switch (event.getEvent()) { case EventBean.Event_SORT_USERS: LogUtil.i(TAG, "用户排序"); List<user> users = (List<user>)event.getData(); sortUsers(users); break; default: break; } }
—————————————————————2016-04-26——————————————————————
用Android Studio 加载了EventBus的Library;发现已经升级到3.0了,用法有变化:
主要是订阅(接收)事件消息的方法上,需要一个注解,这个比较麻烦
订阅事件的方法随意命名(即不用像老版本一样,必须使用约定的方法名),只要在方法上加一个注解
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Subscribe { ThreadMode threadMode() default ThreadMode.PostThread; boolean sticky() default false; int priority() default 0; }
使用如下:
@Subscribe(threadMode = ThreadMode.MainThread, sticky = true, priority = 1) public void onEvent(EventBean event){}
注解中的属性,都有默认值的:
threadMode 表示在哪个线程中接收消息
sticky 如果为true,表示收到粘性事件;相应的在发送事件时,要使用postSticky(Object event);
priority 优先级,值越大,越先处理
关于sticky,EventBus类中源码:
/** * Posts the given event to the event bus and holds on to the event (because it is sticky). The most recent sticky * event of an event's type is kept in memory for future access by subscribers using {@link Subscribe#sticky()}. */ public void postSticky(Object event) { synchronized (stickyEvents) { stickyEvents.put(event.getClass(), event); } // Should be posted after it is putted, in case the subscriber wants to remove immediately post(event); } /** * Gets the most recent sticky event for the given type. * * @see #postSticky(Object) */ public <T> T getStickyEvent(Class<T> eventType) { synchronized (stickyEvents) { return eventType.cast(stickyEvents.get(eventType)); } }
源码中的stickyEvents是一个Map类型。由此可见,多次postSticky同一类型后,
由getStickyEvent(class),可以拿到最新的该类型对象
其它方法:
eventbus.removeAllStickyEvents(); //删除所有粘性事件
eventbus.cancelEventDelivery(Object event); //取消事件提供(发送)
相关文章推荐
- Android消息通信之无所不能的第三方开源项目EventBus
- Android消息通信之无所不能的第三方开源项目EventBus
- 【开源项目11】组件间通信利器EventBus
- 一、概述 EventBus是一款针对Android优化的发布/订阅事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间
- 【开源项目11】组件间通信利器EventBus
- 解开Android应用程序组件Activity的"singleTask"之谜
- 开源异步处项目Droid-Fu详解 For Android: BetterActivity, BetterService And BetterAsyncTask
- Android应用程序四大组件之Activity(二)
- Android中ActivityManagerService与应用程序(客户端)通信模型分析
- Android中ActivityManagerService与应用程序(客户端)通信模型分析
- 解开Android应用程序组件Activity的"singleTask"之谜
- Android中ActivityManagerService与应用程序(客户端)通信模型分析
- 解开Android应用程序组件Activity的"singleTask"之谜(1)
- android开发中fragment的引用以及fragment与activity之间通信的概述
- 解开Android应用程序组件Activity的"singleTask"之谜
- Android中Activity、Service和线程之间的通信
- 解开Android应用程序组件Activity的"singleTask"之谜
- 解开Android应用程序组件Activity的"singleTask"之谜(3)
- Android 四大组件之(1)Activity与Intent通信机制
- 转:解开Android应用程序组件Activity的”singleTask”之谜