之前一直都在用接口回调,或者是handler,感觉确实挺麻烦的,看到好多人都在用EventBus,并且之前自己也用过,但是不是很熟悉,所幸就记录下自己的使用心得。
1.前言:
在项目开发过程中,组件,线程的通信可谓用的非常之多,实现通信的方式大多就是使用Handler通信,或者是AsycTask实现UI的更新,亦或者可以通过接口的回调,来实现通信,另外还可以通过广播来更新信息。但是上述的几种通信方式大多都是代码量大,耦合度较高,使用起来比较繁琐。今天就来一起学习下EventBus.
2.简介:
EventBus是一种用于Android的发布/订阅事件总线,能够简化各组件间的通信,让我们的代码书写变得简单,能有效的分离事件发送方和接收方(也就是解耦的意思),能避免复杂和容易出错的依赖性和生命周期问题。
3.组成
EventBus由三部分组成:
(1) Event事件,也就是需要发送的消息
(2)Subscriber 事件订阅者.在3.0之后事件处理的方法名可以随意取,但是需要加上注解@subscribe(),并且指定线程模型
(3)Publisher 事件的发布者。我们可以在任意线程里发布事件,使用EventBus.getDefault()就可以得到一个EventBus对象,然后再调用post()方法即可。
4.线程模型
EventBus3.0有四种线程模型,分别是:
POSTING (默认) 表示事件处理函数的线程跟发布事件的线程在同一个线程。
MAIN 表示事件处理函数的线程在主线程(UI)线程,因此在这里不能进行耗时操作。
BACKGROUND 表示事件处理函数的线程在后台线程,因此不能进行UI操作。如果发布事件的线程是主线程(UI线程),那么事件处理函数将会开启一个后台线程,如果果发布事件的线程是在后台线程,那么事件处理函数就使用该线程。
ASYNC 表示无论事件发布的线程是哪一个,事件处理函数始终会新建一个子线程运行,同样不能进行UI操作。
5.基本使用
EventBus的使用非常简单,主要分为5个步骤:
定义事件。
注册事件。
订阅事件。
发布事件。
注销事件。
(1)定义一个事件,事件可以是任意普通的Java对象,没有任何特殊的要求
public class MessageEvent {
private String message;
public MessageEvent(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
(2).注册事件,一般选择在Activity的onCreate()方法里去注册EventBus,在onDestory()方法里,去解除注册
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
(3)订阅事件,处理消息的方法名字可以随便取。但是需要加一个注解@Subscribe,并且要指定线程模型。
@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
}
(4)发布事件,在需要的地方发布事件,所有订阅了该类型事件并已注册的订阅者将收到该事件
EventBus.getDefault().post(new MessageEvent("Hello EventBus!"));
(5)注销事件
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
6.完整Demo
第一步:添加依赖
compile 'org.greenrobot:eventbus:3.0.0'
第二步:定义消息事件类
public class MessageEvent{
private String message;
public MessageEvent(String message){
this.message=message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
第三步:注册和解除注册以及订阅事件
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private TextView mTvMessage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initContentView();
// 注册订阅者
EventBus.getDefault().register(this);
}
private void initContentView() {
Button btnStart = findViewById(R.id.btn_main_start_activity);
mTvMessage = findViewById(R.id.tv_main_message);
btnStart.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_main_start_activity) {
SecondActivity.start(this);
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {
Log.i(TAG, "message is " + event.getMessage());
// 更新界面
mTvMessage.setText(event.getMessage());
}
@Override
protected void onDestroy() {
super.onDestroy();
// 注销订阅者
EventBus.getDefault().unregister(this);
}
}
第四步:发布事件
public class SecondActivity extends AppCompatActivity implements View.OnClickListener {
public static void start(Context context) {
Intent intent = new Intent(context, SecondActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
initContentView();
}
private void initContentView() {
findViewById(R.id.btn_second_post_event).setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_second_post_event) {
// 发布事件
EventBus.getDefault().post(new MessageEvent("Hello EventBus!"));
}
}
}
7.粘性事件
如果先发布了事件,然后有订阅者订阅了该事件,那么除非再次发布该事件,否则订阅者将永远接收不到该事件。此时,可以使用粘性事件。发布一个粘性事件之后,EventBus将在内存中缓存该粘性事件。当有订阅者订阅了该粘性事件,订阅者将接收到该事件。注意:sticky = true,一定要写,默认是false .
订阅和发布一个粘性事件
// 订阅粘性事件
@Subscribe(sticky = true)
public void onMessageEvent(MessageEvent event) {
...
}
// 发布粘性事件
EventBus.getDefault().postSticky(new MessageEvent("Hello EventBus!"));
发布一个粘性事件之后,EventBus将一直缓存该粘性事件。如果想要移除粘性事件,那么可以使用如下方法:
// 移除指定的粘性事件
removeStickyEvent(Object event);
// 移除指定类型的粘性事件
removeStickyEvent(Class<T> eventType);
// 移除所有的粘性事件
removeAllStickyEvents();
Demo 如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initContentView();
}
private void initContentView() {
findViewById(R.id.btn_main_post_event).setOnClickListener(this);
findViewById(R.id.btn_main_start_activity).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_main_post_event:
// 发布粘性事件
EventBus.getDefault().postSticky(new MessageEvent("Hello EventBus!"));
break;
case R.id.btn_main_start_activity:
SecondActivity.start(this);
break;
default:
break;
}
}
}
当点击发布粘性事件的按钮时,MainActivity将发布一个MessageEvent粘性事件。
订阅粘性事件的代码如下所示:
public class SecondActivity extends AppCompatActivity {
private static final String TAG = "SecondActivity";
private TextView mTvMessage;
public static void start(Context context) {
Intent intent = new Intent(context, SecondActivity.class);
context.startActivity(intent);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
initContentView();
// 注册订阅者
EventBus.getDefault().register(this);
}
private void initContentView() {
mTvMessage = findViewById(R.id.tv_second_message);
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onMessageEvent(MessageEvent event) {
Log.i(TAG, "message is " + event.getMessage());
// 更新界面
mTvMessage.setText(event.getMessage());
// 移除粘性事件
EventBus.getDefault().removeStickyEvent(event);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 注销订阅者
EventBus.getDefault().unregister(this);
}
}
SecondActivity订阅了MessageEvent粘性事件。当接收到MessageEvent粘性事件时,订阅者方法将打印日志消息,并更新界面上的TextView,最后移除该粘性事件重点内容
总结
经过这个简单的例子,我们发现EventBus使用起来是如此的方便,当我们的代码量变得很多的时候,使用EventBus后你的逻辑非常的清晰,并且代码之间高度解耦,在进行组件、页面间通信的时候,EventBus是一个不错的选择。
参考:
https://blog.csdn.net/u012317510/article/details/78935720
https://www.jianshu.com/p/f9ae5691e1bb