前言
Android optimized event bus that simplifies communication between Activities, Fragments, Threads, Services, etc. Less code, better quality.
Android优化的事件总线,简化了Activity、Fragment、线程、服务等之间的通信,代码更少,质量更好。这是EventBus官网上对其的描述。
1.什么是EventBus
Publisher(事件发布者)将事件post(发布)到EventBus(事件总线中),通过事件总线的传输,将事件传递给Subscriber(事件订阅者)来处理。这就是EventBus的核心思想。
2.几个重要概念
三个对象
Event:事件,可以使任意类型的对象。
Subscriber:事件订阅者,可以声明一个方法来处理接收到的事件,但需要添加一个注解@Subscribe并且指定线程模型,默认为POSTING,关于线程模型会在后面分析。
Publisher:事件发布者,一般通过EventBus.getDefault()方法来实例化,也可以自己实例化,通过post()方法发布事件。
四个线程模型
POSTING(默认):
如果使用事件处理函数指定了线程模型为POSTING,那么该事件在哪个线程发布出来的,事件处理函数就会在这个线程中运行,也就是说发布事件和接收事件在同一个线程。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR。
MAIN:
事件的处理会在UI线程中执行。事件处理时间不能太长,长了会ANR的。
BACKGROUND:
如果事件是在UI线程中发布出来的,那么该事件处理函数就会在新的线程中运行,如果事件本来就是子线程中发布出来的,那么该事件处理函数直接在发布事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。
ASYNC:
无论事件在哪个线程发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。
3.如何使用
按照官网上的介绍,使用过程拢共分为三步:
1.定义事
public class MessageEvent{
......
}
2.准备Subscribers
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
public void onMessageEvent(MessageEvent event) {/* Do something */};
注册和解除注册Subscribers
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
3.发送事件
EventBus.getDefault().post(new MessageEvent());
4.应用实例
添加依赖
compile 'org.greenrobot:eventbus:3.0.0'
定义消息事件
public class MessageEvent {
private String eventMessage;
public MessageEvent(String eventMessage) {
this.eventMessage = eventMessage;
}
public String getEventMessage() {
return eventMessage;
}
public void setEventMessage(String eventMessage) {
this.eventMessage = eventMessage;
}
}
private String eventMessage;
public MessageEvent(String eventMessage) {
this.eventMessage = eventMessage;
}
public String getEventMessage() {
return eventMessage;
}
public void setEventMessage(String eventMessage) {
this.eventMessage = eventMessage;
}
}
注册和解除注册订阅事件
public class MainActivity extends AppCompatActivity {
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
mTv = ((TextView) findViewById(R.id.tv));
//注册事件
EventBus.getDefault().register(this);
}
public void gotoSecond(View view){
private TextView mTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
mTv = ((TextView) findViewById(R.id.tv));
//注册事件
EventBus.getDefault().register(this);
}
public void gotoSecond(View view){
//跳转到第二个界面
startActivity(new Intent(this,SecondActivity.class));
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
startActivity(new Intent(this,SecondActivity.class));
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
处理订阅的事件
这里让TextView展示接收到的消息,因为是更新UI,所以在MAIN线程中执行
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoonEvent(MessageEvent messageEvent){
mTv.setText(messageEvent.getEventMessage());
}
public void onMoonEvent(MessageEvent messageEvent){
mTv.setText(messageEvent.getEventMessage());
}
事件发布者发布事件
public class SecondActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
public void sendEvent(View view){
EventBus.getDefault().post(new MessageEvent("欢迎来到德莱联盟!!!"));
finish();
}
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
public void sendEvent(View view){
EventBus.getDefault().post(new MessageEvent("欢迎来到德莱联盟!!!"));
finish();
}
}
运行程序,效果如下:
点击按钮跳转到第二个Activity,第二个界面中点击按钮发送事件,此时第二个界面finish掉,在第一个界面的Textview上显示“欢迎来到德莱联盟!!!”
5.粘性事件(Sticky Events)
Some events carry information that is of interest after the event is posted. For example, an event signals that some initialization is complete. Or if you have some sensor or location data and you want to hold on the most recent values. Instead of implementing your own caching, you can use sticky events. So EventBus keeps the last sticky event of a certain type in memory. Then the sticky event can be delivered to subscribers or queried explicitly. Thus, you don’t need any special logic to consider already available data.
这是官方对于粘性事件的描述,想必大家看完后已经一目了然了。。。大兄弟消消气,先放下手中的西瓜刀。
其实所谓粘性事件就是在事件发布后再去订阅,仍然能接收到事件消息。因为事件被保存在了内存中。
修改之前的代码,在MainActivity中做如下修改
订阅粘性事件
public void registerEvent(View view){
//注册事件
EventBus.getDefault().register(MainActivity.this);
}
//注册事件
EventBus.getDefault().register(MainActivity.this);
}
处理接收到的粘性事件
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void ononMoonStickyEvent(MessageEvent messageEvent){
mTv.setText(messageEvent.getEventMessage());
}
public void ononMoonStickyEvent(MessageEvent messageEvent){
mTv.setText(messageEvent.getEventMessage());
}
在第二个界面定义点击事件来发送粘性事件
public void sendStickyEvent(View view){
EventBus.getDefault().postSticky(new MessageEvent("这是粘性事件!!!"));
finish();
}
EventBus.getDefault().postSticky(new MessageEvent("这是粘性事件!!!"));
finish();
}
运行效果如下:
在MainActivity中没有订阅事件,直接跳转到SecondActivity,然后点击按钮发送粘性事件,回到ManActivity,TextView没有变化,显示的仍然是“这是第一个界面”,这是因为我们没有注册订阅事件
此时在MainActivity中点击注册事件按钮,TextView显示“粘性事件”。
大功告成!