Android 线程、组件之间通信可以通过Handler消息处理器,BroadCast广播,Service服务等。
这儿介绍的EventBus是一款针对Android优化的发布/订阅的事件总线,可以替代上述的方法,进行线程之间传递消息.优点是开销小,代码更优雅。
EventBus主要是基于观察者模式,特点:
可以向不同的线程中发布事件,在ThreadMode 枚举中定义了4个线程,只需要在事件响应函数注解上加上ThreadMode ,则该事件响应函数就会在对应的线程中执行,ThreadMode定义的4个线程类型如下:
1、PostThread:事件响应函数和事件发布在同一线程中执行。这个是默认值,这样可以避免线程切换。
2、MainThread:事件响应函数会在Android应用的主线程(大部分情况下都是UI线程)中执行。
3、事件响应函数会在一个后台线程中执行。如果事件发布函数不是在主线程中,则会立即在事件发布线程中执行响应函数。如果事件发布函数在主线程中,EventBus则会在唯一的一个后台线程中按照顺序来执行所有的后台事件响应函数。
4、async:事件响应函数在另外一个异步线程中执行。该线程和发布线程、主线程相互独立。如果事件响应函数需要较长的时间来执行,则应该使用该模式,例如 网络访问等。需要注意的是,由于系统并行的限制,应该避免在同一时间触发大量的异步线程。 EventBus使用一个线程池来提高线程的效率。
demo地址: https://github.com/592713711/EventBusDemo
步骤
一 导入EventBus包 (包demo中)
二 将Activity注册成为事件订阅者(观察者)
Java代码 收藏代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册事件总线 让当前对象成为观察者
EventBus.getDefault().register(this);
initView();
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销
EventBus.getDefault().unregister(this);
}
三 在Activity中实现消息回调函数
Java代码
/**
* 观察对象数据改变 触发
* 不加 threadMode 默认在哪发的事件 就从哪个线程执行 ThreadMode.POSTING
* ThreadMode.MAIN:在创建方法中的线程中执行
*
* @param s
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void showInfo(String s) {
Log.d(TAG, "MAIN " + Thread.currentThread().getName() + " " + s);
}
/**
* ThreadMode.POSTING:在发送线程中执行
*
* @param s
*/
@Subscribe(threadMode = ThreadMode.POSTING)
public void showInfo2(String s) {
Log.d(TAG, "POSTING " + Thread.currentThread().getName() + " " + s);
}
/**
* ThreadMode.BACKGROUND:后台执行
* 若是主线程发布事件,会启动子线程执行该方法
* 若在子线程发布事件 就在当前子线程执行该方法
*
* @param s
*/
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void showInfo3(String s) {
Log.d(TAG, "BACKGROUND " + Thread.currentThread().getName() + " " + s);
}
/**
* ThreadMode.ASYNC:在新线程中执行 不管在哪创建和发布 都会新启动一个执行
*
* @param s
*/
@Subscribe(threadMode = ThreadMode.ASYNC)
public void showInfo4(String s) {
Log.d(TAG, "ASYNC " + Thread.currentThread().getName() + " " + s);
}
注意:
1 回调函数必须要加上Subscribe,函数名无要求
2 回调函数的参数决定该接受的类型,上述的函数只能接受传递字符串的消息
四 在子线程中发布消息
Java代码
new Thread(
new Runnable() {
@Override
public void run() {
Log.d(TAG, "发布 " + Thread.currentThread().getName());
EventBus.getDefault().post("info");
}
}
).start();
五 程序输出
可以看出在子线程中发布消息时:
用POSTING模式时方法是在该子线程中执行
用BACKGROUND模式时方法是在该子线程中执行
用MAIN模式时方法是在主线程中执行
用ASYNC模式时在线程池中单独取出一个线程,在其中执行方法
有兴趣的朋友可以试试在主线程中发布消息看看程序输出
补充:
1 由于post时传入的参数是Object,所以回调函数的参数如果要是int的话,必须改为Integer
2 用了EventBus一段时间后,发现并没有像handler中有延迟发送消息的方法,所以感觉EventBus并不能完全替代Handler