EventBus: Android 组件间通讯的高效方式
来源:互联网 发布:中宣部是阎王殿知乎 编辑:程序博客网 时间:2024/05/09 23:21
最近,以EventBus 作为Android 组件间的通讯方式比较流行,在github上找到了EventBus的项目源码及其相关介绍,在此将其中关键部文翻译为中文,并加入一些个人的理解。
EventBus 项目链接:https://github.com/greenrobot/EventBus
EventBus 是一个Android 端优化 的 publish/subscribe 消息总线
EventBus 优势
- 简化组件间的通讯
- 简化代码,使代码更优雅,更易管理
- 速度快
- 容量小(<50k jar)
- 实践证明已有一亿个应用集成EventBus
- 拥有先进的功能,如交付线程、订阅者优先级等
EventBus使用步聚三部走
1.定义事件
EventsBus对事件没有任何特殊的要求
public class MessageEvent { public final String message; public MessageEvent(String message) { this.message = message; }}
2.准备订阅者
订阅者需要实现onEventXXX方法,这个方法会在事件到时被调用。订阅者需要将自己注册到EventBus 中去,在适当的地方解除注册。
@Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); }//这个方法将在MessageEvent 被 post 之后调用; public void onEvent(MessageEvent event){ Toast.makeText(getActivity(), event.message, Toast.LENGTH_SHORT).show(); } //这个方法将在SomeOtherEvent 被 post 之后调用; public void onEvent(SomeOtherEvent event){ doSomethingWith(event); }
3.发布事件
可以从代码的任何地方 post(发布)一个事件,所有拥有和这个事件类型匹配的onEventXXX()方法的订阅者都会收到这个事件(消息)
EventBus.getDefault().post(new MessageEvent("Hello everyone!"));
线程切换和线程模式
EventBus 可以处理线程切换问题,事件可以在任何线程中被发布,也可以在任何线程中被处理。
一个普遍的应用是用于更新UI。在Android 中,更新UI必须在主线程中完成,请求网络等耗时操作不能在主线程中执行,否则在造成界面卡顿阻塞。EventBus 可以轻松地解决这个任务,与UI线程中实现同步(不再需要专注于线程转换,使用AsyncTask,使代码更加简化,更易于管理 );
在EventBus中,可以控制事件处理方法onEventXXX中的代码在哪种线程中执行, 通过使用EventBus中的线程模式可以实现这一点
Subscriber函数的名字只能是4个(onEvent、onEventMainThread、onEventBackgroundThread、onEventAsync),因为每个事件订阅函数都是和一个`ThreadMode相关联的,ThreadMode指定了会调用的函数。有以下四个ThreadMode:
- PostThread(发布线程):
事件的处理在和事件的发送在相同的进程,所以事件处理时间不应太长,不然影响事件的发送线程,而这个线程可能是UI线程。对应的函数名是onEvent。
// Called in Android UI's main thread public void onEventMainThread(MessageEvent event) { textField.setText(event.message); }
- MainThread(主线程):
事件的处理会在UI线程中执行。事件处理时间不能太长,这个不用说的,长了会ANR的,对应的函数名是onEventMainThread。
// Called in Android UI's main thread public void onEventMainThread(MessageEvent event) { textField.setText(event.message); }
- BackgroundThread(后台线程):
事件的处理会在一个后台线程中执行,对应的函数名是onEventBackgroundThread,虽然名字是BackgroundThread,事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接执行事件,如果当前线程是UI线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。
// Called in the background thread public void onEventBackgroundThread(MessageEvent event){ saveToDisk(event.message);
- Async(异步线程):
事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程(EventBus有线程池作管理),但最好限制线程的数目
// Called in a separate thread public void onEventAsync(MessageEvent event){ backend.send(event.message); }
订阅者优先级(Android 广播机制中也有优先级的概念)
在注册订阅者时,可以为订阅者指定优先级,当事件被 post时,处在同一线程模式(ThreadMode)且优先级高的订阅者将先收到这个事件。EventBus 中,默认的优先级是0;
int priority = 1; EventBus.getDefault().register(this, priority);
取消事件传递(类似广播拦截)
可以在订阅者事件处理方法中,通过调用cancelEventDelivery(Object event),取消事件的传递。后继的订阅者将不会接收到这个事件
// Called in the same thread (default) public void onEvent(MessageEvent event){ // Process the event ... EventBus.getDefault().cancelEventDelivery(event) ; }
事件经常是被 优先级较高的订阅者取消继续传递。有一点需要注意,`这个事件的ThreadMode必须是PostThread,并且只能终止它在处理的事件。
Sticky Event (棘手事件?粘性事件?暂且不纠结如何翻译,说说它的应用场景)
当被发布的某些事件中携带着感兴趣的信息。例如,一件事件发送一个某些初始化已经完成的信号。假设你想保存某些传感器或者地理信息的最新数据,你并不需要自己去实现缓存,可以使用sticky events. EventBus 可以在内存中保存最后一个post的sticky 事件。sticky 事件同样可以传递到订阅者那里去,还可以被准确查询(最后一个post 的sticky event)
假设下面是一个在一段时间之前post 的一个sticky event:
EventBus.getDefault().postSticky(new MessageEvent("Hello everyone!"));
然后,一个新的Activity启动。当使用registerSicky注册时,将后立马收到一个最新的sticky event
@Override public void onStart() { super.onStart(); EventBus.getDefault().registerSticky(this); } public void onEventMainThread(MessageEvent event) { textField.setText(event.message); } @Override public void onStop() { EventBus.getDefault().unregister(this); super.onStop(); }
不通过注册,也可以得到一个特定类型的最后一个sticky event
EventBus.getDefault().getStickyEvent(Class<?> eventType)
始终得记住的一点就是:EventBus 只缓存特定类型的最后一个的sticky event
EventBus其它特性:
- 并非基于注解:在Android中注解的查询比较慢,尤其是在Android4.0以下版本
- 基于约定:事件处理方法以“onEventXXX”命名
- 性能优秀:它可能是Android中最快的消息通讯机制
- 方便的单例:调用EventBus.getDefault()可以获取EventBus的实例。你也可以用 new 的方式创建另一辆消息列车
- 订阅者和事件的继承:事件处理方法可以定义在订阅者的父类中,事件的类型也可以用事件的父类声明。
EventBus 缺点:
无法进程间通信,如果一个应用内有多个进程的话就没办法了
注意事项
- 同一个onEvent函数不能被注册两次,所以不能在一个类中注册同时还在父类中注册
- 当Post一个事件时,这个事件类的父类的事件也会被Post。
- Post的事件无Subscriber处理时会Post NoSubscriberEvent事件, 当调用Subscriber 中 onEventXXX 失败时会Post SubscriberExceptionEvent`事件。
- EventBus: Android 组件间通讯的高效方式
- Android组件间通讯之:EventBus
- Android组件间通讯Eventbus日常使用
- EventBus 同一进程中不同组件间的通讯
- EventBus组件间通讯利器【入门篇】
- 使用EventBus进行组件间通讯
- Android组件间通讯
- Android组件间通信库EventBus学习
- Android组件间通信库EventBus学习
- Android组件间通信库EventBus收集
- Android组件间通信框架EventBus
- Android组件间通信——EventBus
- Android组件间通信库EventBus学习
- Android组件间通信库EventBus学习
- Android组件间通信库EventBus学习
- Android 通讯 —— EventBus
- Android组件间通信机解耦——Android EventBus和Otto框架一、前言 传统的事件传递方式包括:Handler、BroadCastReceiver、Interface 回调,相比之
- android进程间通讯方式
- Oracle复习重点
- 由电影Matrix(骇客帝国)联想到的操作系统知识
- 注册——SIP学习笔记(六)
- gcc编译常见问题
- 图片转DATA:URI工具
- EventBus: Android 组件间通讯的高效方式
- Chart图表在Android开发中的应用
- 算法的三种练习
- 慎用memset();
- 进阶之路--数据存储方式--file
- 儿童佩戴石家庄助听器需要注意的事项
- 文章标题
- Climbing Stairs
- 向cookie中存中文乱码问题