前言:EventBus是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过 EventBus 实现。
一、概述
首先,复述一下订阅发布模式。订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听某一个主题对象。这个主题对象在自身状态变化时,会通知所有订阅者对象,使它们能够自动更新自己的状态。
EventBus是一款针对Android优化的发布/订阅事件总线,基于EventBus可以更加便捷地运用订阅发布模式。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息。
原先使用Intent,Handler,BroadCast时,发送和接收必须在相应的组件间进行处理,而使用EventBus后,发送只需post一下,然后定义一个方法去接收即可,其它的事情一概不管,大大地降低了代码间的耦合系数,便于大型项目的开发。
二、使用方法
<span style="font-size:12px;">// 在Activity中注册与反注册
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this); // 注册
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this); // 反注册
}
// 在任意地方新建一个事件类
public class EventBusMsg {}
// 在任意地方调用发送事件
EventBus.getDefault().post(new EventBusMsg());
// 在注册了的Activity中处理事件(3.0前使用特定名称方法,3.0后使用@Subscribe注解,具体下面会详解)
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventBusMsg(EventBusMsg eventBusMsg) {}</span>
三、实战
下面代码所实现的效果是这样的:
1.将EventBus的jar包拷贝到/app/libs目录下,并在bulid.gradle下添加依赖(没有jar包的点击这里下载3.0.1版本):
dependencies {
......
compile files('libs/eventbus-3.0.1.jar')
}
2.修改MainActivity布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.administrator.eventbus.MainActivity">
<Button
android:id="@+id/id_btn_goto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="进入SecondActivity"
android:textAllCaps="false"/>
<TextView
android:id="@+id/id_tv"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="此处显示SecondActivity发送过来的消息"/>
</LinearLayout>
MainActivity布局中有一个Butoon和TextView,Button用来进入SecondActivity,TextView用来显示SecondActivity发过来的消息。
3.新建一个布局,并改成如下代码,这是SecondActivity的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/id_btn_post"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="向MainActivity发送消息"
android:textAllCaps="false"/>
</LinearLayout>
SecondActivity布局中只有一个Button,该Butoon用来给MainActivity发送消息。
4.新建一个事件类EventBusMsg,该类就是EventBus传递的类型:
public class EventBusMsg {
private String mMsg;
public EventBusMsg(String msg) {
mMsg = msg;
}
public String getMsg() {
return mMsg;
}
}
该类通过构造函数放置字符串消息,通过getMsg()获取消息。
5.新建一个SecondActivity,代码如下:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
findViewById(R.id.id_btn_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 发布者发布消息
EventBus.getDefault().post(new EventBusMsg("SecondActivity向您问好!"));
}
});
}
}
该Activity加载了布局并给Button设置了监听器,在监听器中通过EventBus.getDefault().post()发送消息。
6.修改MainActivity代码如下:
public class MainActivity extends AppCompatActivity {
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 注册EventBus
EventBus.getDefault().register(this);
textView = (TextView) findViewById(R.id.id_tv);
findViewById(R.id.id_btn_goto).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), SecondActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this); // 解除EventBus注册
}
/** EventBus 3.0版本后使用@Subscribe注解的方式表明该方法为订阅者处理函数
* threadMode有四种可选值:ThreadMode.MAIN => 在UI线程执行
* ThreadMode.BACKGROUND => 在后台线程执行
* ThreadMode.ASYNC => 创建新的子线程执行
* ThreadMode.POSTING => 在发送线程执行
* 该订阅者接收哪种EventBus.post主要取决于订阅函数内的参数匹配 */
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEventBusMsg(EventBusMsg eventBusMsg) {
String msg = eventBusMsg.getMsg();
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
textView.setText(msg);
}
}
该Activity加载了布局并给Button设置了监听器,监听器中通过Intent意图进入SecondActivity。
接下来就是EventBus的使用了:
①在onCreate()中通过EventBus.getDefault().register(this)注册EventBus
②在onDestroy()中通过EventBus.getDefault().unregister(this)反注册EventBus
③创建了onEventBusMsg()方法,通过该方法接收消息并在TextView上显示出来这里有两点是需要注意的:
⑴EventBus3.0后的版本通过@Subscribe(threadMode = ThreadMode.XXXX)注解该方法为EventBus接收方法。
ThreadMode有四种可选值:MAIN、BACKGROUD、ASYNC、POSTING。
ThreadMode.MAIN表示在UI线程执行,3.0之前使用onEventMainThread方法
ThreadMode.BACKGROUND表示在后台线程执行,3.0之前使用onEventBackground方法
ThreadMode.ASYNC创建一个新的线程执行,3.0之前使用onEventAsync方法
ThreadMode.POSTING表示在发送线程执行,3.0之前使用onEvent方法
⑵如果一个项目中有多种Event,接收方法接收哪种Event取决于方法中的参数类型。
这个理解的时候可以类比广播broadcast,broadcast是通过action进行filter,而EventBus是通过方法中的参数进行filter。
比如上面的例子就是通过onEventBusMsg()方法中的参数EventBusMsg进行过滤,如果该参数与EventBus.getDefault().post()中的参数不匹配则无法接收相应消息。
源代码下载请点击这里