EventBus是使用十分广泛的事件总线框架, 2.0到3.0的变化还是挺大的
今天准备重构代码,关于解耦想到了用EventBus,发现EventBus出了3.0的beta版,使用方式略有区别,特此记录。如果不会用EventBus的,请参考教程。
3.0与2.x的区别
主要区别在订阅函数的不同
EventBus2.x中只暴露了四个方法供用户调用,分别是
- onEvent:该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。
- onEventMainThread:不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。
- onEventBackgroundThread:如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。
- onEventAsync:无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync.
EventBus3.0中必须使用注解,例如:
@Subscribe(threadMode = ThreadMode.Async, sticky = true, priority = 1)
public void firstEvent(FirstEvent event) {
Log.e("TAG", "Async" + Thread.currentThread().getName());
}
好处在于订阅函数可以随便起名字,其他与2.x没什么不同。
这里Subscribe中的key需要解释一下含义,Subscribe中可以传三种值:
-
ThreadMode:这是个枚举,有四个值,决定订阅函数在哪个线程执行
- PostThread:事件发送者在哪个线程就执行在哪个线程。同2.x中的onEvent方法,默认值就是这个
- MainThread:订阅函数一定执行在主线程。同onEventMainThread方法
- BackgroundThread:如果是事件从子线程发出,订阅函数就执行在那个子线程,不会创建新的子线程;如果主线程发出事件,则创建子线程。同onEventBackgroundThread方法
- Async:一定创建子线程。同onEventAsync方法。
-
sticky:默认为false,如果为true,当通过
postSticky
发送一个事件时,这个类型的事件的最后一次事件会被缓存起来,当有订阅者注册时,会把之前缓存起来的这个事件直接发送给它。使用在比如事件发送者先启动了,订阅者还没启动的情况。 -
priority:默认值为0。订阅了同一个事件的订阅函数,在ThreadMode值相同的前提下,收到事件的优先级。
具体使用
创建事件:
public class FirstEvent {
private String msg;
public FirstEvent(String msg){
this.msg = msg;
}
public String getMsg(){
return msg;
}
}
在MainActivity的onCreate方法中注册,onDestroy方法中反注册
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
订阅函数,此处用来查看执行在哪个线程(注意,这里的函数名可以任取):
@Subscribe(threadMode = ThreadMode.Async, sticky = true, priority = 1)
public void onAsync(FirstEvent event) {
Log.e("TAG", "Async: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BackgroundThread)
public void onBackgroundThread(FirstEvent event) {
Log.e("TAG", "BackgroundThread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.MainThread)
public void onMainThread(FirstEvent event) {
Log.e("TAG", "MainThread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.PostThread)
public void onPostThread(FirstEvent event) {
Log.e("TAG", "PostThread: " + Thread.currentThread().getName());
}
在SecondActivity发送事件(主线程中发送):
EventBus.getDefault().post(new FirstEvent("啦啦啦"));
执行结果如下:
Async: pool-1-thread-1
MainThread: main
PostThread: main
BackgroundThread: pool-1-thread-2
如果是在子线程中发送:
new Thread(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new FirstEvent("啦啦啦"));
}
}).start();
执行结果如下:
BackgroundThread: Thread-450
PostThread: Thread-450
Async: pool-1-thread-1
MainThread: main
如果先启动SecondActivity,后启动MainActivity:
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new FirstEvent("啦啦啦"));
startActivity(new Intent(SecondActivity.this,MainActivity.class));
}
确实只有onAsync方法收到了消息。
至此对EventBus的试验基本就结束了,各位可以自行选择不同的ThreadMode值,让订阅函数执行在不同的线程。根据需要选择是否需要sticky=true。
完整的MainActivity和SecondActivity代码如下(xml文件就不贴了,就一个Button):
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
findViewById(R.id.btn).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this,
SecondActivity.class));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.Async, sticky = true, priority = 1)
public void onAsync(FirstEvent event) {
Log.e("TAG", "Async: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BackgroundThread)
public void onBackgroundThread(FirstEvent event) {
Log.e("TAG", "BackgroundThread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.MainThread)
public void onMainThread(FirstEvent event) {
Log.e("TAG", "MainThread: " + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.PostThread)
public void onPostThread(FirstEvent event) {
Log.e("TAG", "PostThread: " + Thread.currentThread().getName());
}
}
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
findViewById(R.id.second).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().postSticky(new FirstEvent("Lai自星星的我"));
startActivity(new Intent(SecondActivity.this,MainActivity.class));
}
});
}
}
参考链接
EventBus所有版本的Marven仓库
EventBus2.x使用教程
快速Android开发系列通信篇之EventBus
网友评论