【Android高级】Android组件间通信库EventBus学习

      最近偶然在论坛上看了一个比较厉害的库EventBus,感觉使用起来很爽,不用考虑在Activity还是Fragment,不用担心是不是UI线程,随便怎么通信都行,有网友笑说这简直是Android开发中的第五大组件,通信起来像广播那样神通,但又比广播轻量级多了,所以在这里记下来,以后开发就方便多了。

项目地址:https://github.com/greenrobot/EventBus

EventBus主要特点

1. 事件订阅函数不是基于注解(Annotation)的,而是基于命名约定的,在Android 4.0之前的版本中,注解解析起来比较慢 , 事件响应函数默认以“onEvent”开始,可以在EventBus中修改这个值,但是不推荐这么干
2. 事件响应有更多的线程选择
EventBus可以向不同的线程中发布事件,在ThreadMode 枚举中定义了4个线程,只需要在事件响应函数名称“onEvent”后面添加对应的线程类型名称,则还事件响应函数就会在对应的线程中执行,比如事件函数“onEventAsync”就会在另外一个异步线程中执行,ThreadMode定义的4个线程类型如下:
PostThread:事件响应函数和事件发布在同一线程中执行。这个是默认值,这样可以避免线程切换。
MainThread:事件响应函数会在Android应用的主线程(大部分情况下都是UI线程)中执行。
BackgroundThread:事件响应函数会在一个后台线程中执行。如果事件发布函数不是在主线程中,则会立即在事件发布线程中执行响应函数。如果事件发布函数在主线程中,EventBus则会在唯一的一个后台线程中按照顺序来执行所有的后台事件响应函数。

上面的3种事件响应函数,应该能够很快的执行完,不然的话会阻塞各自的事件发布。

async:事件响应函数在另外一个异步线程中执行。该线程和发布线程、主线程相互独立。如果事件响应函数需要较长的时间来执行,则应该使用该模式,例如 网络访问等。需要注意的是,由于系统并行的限制,应该避免在同一时间触发大量的异步线程。 EventBus使用一个线程池来提高线程的效率。

3. EventBus支持 Sticky Event

有时候某个事件可能会用到多次,比如在前面介绍Event Bus模型一文的示例中,最新的位置更新信息,可能需要多次用到,真对这种情况,您可以把该事件发布为Sticky Event,然后,当需要查询该信息的时候,可以通过Bus的getStickyEvent(ClasseventType) 函数来查询最新发布的Event对象。
同一类型的事件只保存最新的Event对象。
注册和发布事件的函数分别为 registerSticky(…) 和 postSticky(Object event)
在项目主页上还有和Otto之间性能对比的表格,以及性能测试的源码。

注意事项:

不管是生产者还是订阅者都需要向Bus注册自己:

bus.register(this);
在每个Activity或者Fragment的onResume和onPause函数中都需要调用bus.register(this)和bus.unregister(this)函数比较麻烦,可以通过一个Bus包装类来自动完成注册的工作,然后在类中只需要继承基类,并调用函数getScopedBus().register(…) 来注册需要的对象即可。详细情况参考示例代码:https://gist.github.com/3057437

使用示例:

onCreate()中注册bus:

[java] view plaincopy技术分享技术分享
  1. //注册:三个参数分别是,消息订阅者(接收者),接收方法名,事件类  
  2.         EventBus.getDefault().register(this,"setTextA",SetTextAEvent.class);  
  3.         EventBus.getDefault().register(this,"setTextB",SetTextBEvent.class);  
  4. //        EventBus.getDefault().register(this,"messageFromSecondActivity",SecondActivityEvent.class);  
  5.         EventBus.getDefault().registerSticky(this"messageFromSecondActivity", SecondActivityEvent.class);  
  6.         EventBus.getDefault().register(this,"countDown",CountDownEvent.class);  

对应event函数:

[java] view plaincopy技术分享技术分享
  1. /** 
  2.  * 与注册对应的方法名和参数,没有后缀,默认使用PostThread模式,即跟发送事件在同一线程执行 
  3.  * @param event 
  4.  */  
  5. public void setTextA(SetTextAEvent event)  
  6. {  
  7.     textView.setText("A");  
  8. }  
  9. public void setTextB(SetTextBEvent event)  
  10. {  
  11.     textView.setText("B");  
  12. }  
  13. public void messageFromSecondActivity(SecondActivityEvent event)  
  14. {  
  15.     textView.setText(event.getText());  
  16. }  
  17.   
  18. /** 
  19.  * 加Async后缀,异步执行。还有MainThread和BackgroundThread,分别是在主线程(UI)执行和后台线程(单一)执行 
  20.  * @param event 
  21.  */  
  22. public void countDownAsync(CountDownEvent event)  
  23. {  
  24.     for(int i=event.getMax();i>0;i--)  
  25.     {  
  26.         Log.v("CountDown", String.valueOf(i));  
  27.         SystemClock.sleep(1000);  
  28.     }  
  29. }  

secondActivity中发送

[java] view plaincopy技术分享技术分享
  1. //postSticky会缓存最新的event事件,不管接收方是否消亡,载入时都会检测最新状态  
  2. EventBus.getDefault().postSticky(new SecondActivityEvent("Message From SecondActivity"));  
  

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。