简介
EventBus是针一款Android的发布/订阅事件总线。它能让我们很轻松优雅的在各个组件间传递信息,甚至是线程间的消息传递,而且代码耦合低。
使用
- 项目中引用,现在最新版本是3.0.0
compile 'org.greenrobot:eventbus:3.0.0'
- 定义消息类
public class FirstEvent {
private String msg;
public FirstEvent(String msg) {
this.msg = msg;
}
public String getMsg() { return this.msg; }
}
- 订阅事件
EventBus.getDefault().register(this);
- 发送事件
EventBus.getDefault().post(new FirstEvent("post first event"));
- 处理事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(FirstEvent firstEvent) {
Toast.makeText(this, "receive msg-->" + firstEvent.getMsg(), Toast.LENGTH_SHORT).show();
}
- 取消订阅事件
EventBus.getDefault().unregister(this);
注意
- EventBus3.0以后采用了注解的方式,处理事件的方法名字可以任意取名字,但是要加注解@Subscribe,后面的threadMode为线程模型。
- 事件处理函数的访问权限必须为public
EventBus的线程模型
EventBus的事件处理函数需要指定线程模型,也就是指定处理函数运行的线程。一共有四种线程模型:ThreadMode.POSTING、ThreadMode.MAIN、ThreadMode.BACKGROUND与ThreadMode.ASYNC。
- ThreadMode.POSTING:事件处理函数和发布事件在同一个线程,即事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行。在线程模型为PostThread的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
- ThreadMode.MAIN:不论事件是在哪个线程中发布出来的,该事件处理函数都会在UI线程中执行。该方法可以用来更新UI,但是不能处理耗时操作。
- ThreadMode.BACKGROUND:如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
- ThreadMode.ASYNC:无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行。同样,此事件处理函数中禁止进行UI更新操作。
示例
事件处理函数
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMain(FirstEvent firstEvent) {
Log.e("ThreadModeMain-->", Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEventAsync(FirstEvent firstEvent) {
Log.e("ThreadModeAsync-->", Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEventBackground(FirstEvent firstEvent) {
Log.e("ThreadModeBackground-->", Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEventPosting(FirstEvent firstEvent) {
Log.e("ThreadModePosting-->", Thread.currentThread().getName());
}
从UI线程发送事件
- 发送事件
btn_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new FirstEvent("send msg"));
}
});
- 输出Log:
07-07 17:05:46.709 26041-26041/com.xxq2dream.explorer E/post event-->: main
07-07 17:05:46.711 26041-26041/com.xxq2dream.explorer E/ThreadModeMain-->: main
07-07 17:05:46.711 26041-26765/com.xxq2dream.explorer E/ThreadModeAsync-->: pool-1-thread-1
07-07 17:05:46.711 26041-26041/com.xxq2dream.explorer E/ThreadModePosting-->: main
07-07 17:05:46.712 26041-26766/com.xxq2dream.explorer E/ThreadModeBackground-->: pool-1-thread-2
- 可以看出POSTING和MAIN的处理函数和发送事件的线程一样,都在UI线程,ASYNC的线程处理函数在新线程pool-1-thread-1,BACKGROUND的线程处理函数在新线程pool-1-thread-2
从子线程发送事件
- 发送事件
btn_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new FirstEvent("send msg"));
}
});
}
});
- 输出Log
07-07 17:10:02.560 29408-29809/com.xxq2dream.explorer E/post event-->: Thread-20772
07-07 17:10:02.563 29408-29809/com.xxq2dream.explorer E/ThreadModeBackground-->: Thread-20772
07-07 17:10:02.563 29408-29809/com.xxq2dream.explorer E/ThreadModePosting-->: Thread-20772
07-07 17:10:02.564 29408-29810/com.xxq2dream.explorer E/ThreadModeAsync-->: pool-1-thread-1
07-07 17:10:02.570 29408-29408/com.xxq2dream.explorer E/ThreadModeMain-->: main
- 可以看到MAIN的处理函数在UI线程,由于是从子线程发出事件,BACKGROUND和POSTING的线程处理函数都在发出事件的线程中执行,而ASYNC的线程处理函数在新线程pool-1-thread-1中执行
黏性事件
EventBus还支持发送黏性事件。黏性事件就是在发布事件以后再订阅事件,也能收到之前发送的事件。但是,如果在订阅前发送了多个事件,则只能收到最近的一次的发送事件。
示例
- 首先在未订阅的情况下发送事件
- 然后订阅后看是否还能收到事件
07-07 17:32:45.511 12248-12248/com.xxq2dream.explorer E/post event-->: main
07-07 17:32:47.474 12248-12248/com.xxq2dream.explorer E/ThreadModeMain-->: main
07-07 17:32:47.474 12248-12423/com.xxq2dream.explorer E/ThreadModeAsync-->: pool-1-thread-1
07-07 17:32:47.474 12248-12248/com.xxq2dream.explorer E/ThreadModePosting-->: main
07-07 17:32:47.475 12248-12424/com.xxq2dream.explorer E/ThreadModeBackground-->: pool-1-thread-2
- 从Log可以看出订阅后仍然可以收到之前发送的事件
验证只能收到订阅前的最近的一次事件
- 只要在订阅前发送多次事件,然后订阅以后查看Log即可
07-07 17:41:51.272 16629-16629/com.xxq2dream.explorer E/ThreadModeMain-->: event3
07-07 17:41:51.272 16629-18692/com.xxq2dream.explorer E/ThreadModeAsync-->: event3
07-07 17:41:51.272 16629-16629/com.xxq2dream.explorer E/ThreadModePosting-->: event3
07-07 17:41:51.273 16629-18693/com.xxq2dream.explorer E/ThreadModeBackground-->: event3
以上就是EventBus的详细使用攻略啦!
欢迎关注我的公众号,和我一起每天进步一点点!
