前言: 青春不是一个年纪的终结,也不是面孔的日益干瘪,而是永远有冲刺梦想的心情和挑战的勇气。
一、概述
EventBus是适用于Android和Java的发布/订阅事件总线。主要功能是替代Intent、Handler、BroadCast在Activity、Fragment、Service线程之间传递消息。EventBus能够简化应用组件间的通信,解耦(有效分离)事件的发送者和接收者,避免复杂和容易出错的依赖和生命周期问题,开销小,代码更优雅。
Andorid组件间通信,可能都是用Handler消息机制或者广播机制来实现通信,但是它们代码量大,组件上容易产生耦合 。为什么选择使用EventBus来做通信?
- 简化了组件间间的通信;
- 对事件通信双方进行解耦 ;
- 在Activity、Fragment和后台线程中能很好使用;
- 避免了复杂且容易出错的依赖性和生命周期问题 ;
- 可以灵活方便指定工作线程和优先级 ;
- 速度快,性能好,代码简单优雅;
- 库比较小,不占内存。
二、使用步骤
(1)定义事件对象
事件对象可以是任意java类型,没有特殊要求,比如String、int、自定义类等。
public class MessageEvent {
public String name;
}
(2)在接收消息的页面注册事件
EventBus.getDefault().register(this);
● register(Object subscriber): EventBus订阅事件的方法,通过EventBus.getDefault()
获取事件总线实例;参数subscriber为订阅者,订阅者有处理事件的方法,并且必须添加@Subscribe注解。
只有注册了订阅事件,才会接收到消息。注意:通常根据Activity和Fragment的生命周期注册和注销事件。
(3)订阅者实现事件处理方法
也称为"订阅者方法",当发布对应事件类型时,该方法被调用(在接收消息的页面)。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent message){
//TODO 接收事件后Do something
}
● @Subscribe: 必须使用@Subscribe注解来定义订阅者方法,否则事件处理方法无法生效。
● threadMode: 线程模式,表示在哪个线程里面执行,ThreadMode.MAIN表示在主线程执行该方法。(其他模式在下一篇讲解)
● onMessageEvent(MessageEvent message): 事件处理方法的方法名称,onMessageEvent()
是任意的合法方法名,开发者可以自己定义;参数类型MessageEvent为定义接收事件的对象类型,要与发布事件的类型一致,否则无法接收事件。
(4)发布事件
EventBus.getDefault().post(Object event);
● post(Object event): EventBus发送事件的方法,参数event为事件对象,是Object任意类型,这里发送的类型需要与接收事件的类型一致。
当前与事件类型匹配的所有已注册的事件都会接收到。
(5)在接收消息的页面注销(解除注册)事件
EventBus.getDefault().unregister(this);
● unregister(Object subscriber): 给订阅者注销事件的方法,如果事件不需要使用了必须调用该方法注销事件。
当消息页面不存在或者不需要事件了注销该事件。
三、项目实战
3.1 普通使用
我们首先来演示个例子,在OneActivity中注册事件并实现事件处理方法,点击按钮跳转到TwoActivity中,点击TwoActivity的“发送事件”按钮向OneActivity发送事件,OneActivity在接收到事件信息后吐司并将接收的数据显示在屏幕上。
我们按照下面的步骤实现这个效果:
(1)使用EventBus需要在build.gradle文件中添加依赖:
添加EventBus3.2依赖:
implementation 'org.greenrobot:eventbus:3.2.0'
(2)定义事件对象
事件对象可以是任意java类型(Object),没有特殊要求,比如String、int、自定义类等,开发者可以根据需求选择。这里我们定义一个类MessageEvent:
public class MessageEvent {
public MessageEvent(String name) {
this.name = name;
}
public String name;
}
这个类很简单,只定义了一个参数name,构造时传入一个字符串。它是用于我们发送事件的事件对象携带参数的封装类,在下面订阅者方法接收的参数中也是以MessageEvent为接收类型才能接收到。两个类型要一致才能成功接收到发出的数据。
(3)在接收消息的页面注册和注销事件
从上面的效果可以看到在OneActivity中接收到事件消息,那么我们需要在OneActivity注册和注销事件,通常根据Activity和Fragment的生命周期注册和注销事件。那么我们在Activity的onCreate()
方法中注册事件,在onDestroy()
方法中注销事件:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
只有消息页面存在并且注册了订阅事件,发布的事件才会接收到。当消息页面不存在或者不需要事件了注销该事件。
注意:如果消息页面不存在或者页面已经被销毁了,发布的事件是无法接收到的。所以发布事件前需要明确接收消息的页面已经创建并且注册了事件。另外,粘性事件能实现先发布事件,后续再注册事件,这样也能接收事件,下面会讲解。
(4)订阅者实现事件处理的方法
需要在消息页面OneActivity实现事件处理的方法,也称为"订阅者方法",当发布对应事件类型时,该方法被调用,接收到事件的消息。定义一个接收事件的方法onMessageEvent()
,将接收的数据设置到mTv_content控件中,并且吐司显示。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent message) {
//TODO 接收事件后Do something
mTv_content.setText("onMessageEvent:" + message.name);
Toast.makeText(this, "onMessageEvent:" + message.name, Toast.LENGTH_SHORT).show();
}
必须使用@Subscribe()
注解来定义订阅者方法,并且在里面声明threadMode线程模式,这里为在主线程ThreadMode.MAIN
中接收数据,方法名onMessageEvent()
是任意的合法方法名,开发者可以自己定义,参数类型MessageEvent为定义事件的对象类型,要与发布事件的类型一致,否则无法接收事件。
(5)发布事件
发送事件是在TwoActivity中是实现的,通过EventBus中的Psot()
方法发布事件,参数为上面自定义的MessageEvent,可以将携带的数据写入MessageEvent中,这里对象的类型要与接收事件的类型一致。
EventBus.getDefault().post(new MessageEvent("接收到TwoActivity发送过来的事件啦"));
那么整个过程就完成了,是不是很简单,这里贴出两个Activity的代码,其他代码就不一一贴出来了,比较简单。(源码在文章最后给出)
接收消息页面:OneActivity.java
/**
* 注册并接收普通事件
*/
public class OneActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);
findViewById(R.id.btn_skip).setOnClickListener(this);
mTv_content = findViewById(R.id.tv_content);
//1.注册事件
EventBus.getDefault().register(this);
}
//3.接收事件处理
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent message) {
//TODO 接收事件后Do something
mTv_content.setText("onMessageEvent:" + message.name);
Toast.makeText(this, "onMessageEvent:" + message.name, Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_skip://跳转到TwoActivity
startActivity(new Intent(this, TwoActivity.class));
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
}
发送消息页面:TwoActivity.java
/**
* 发布普通事件
*/
public class TwoActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
findViewById(R.id.btn_send).setOnClickListener(this);
mTv_content = findViewById(R.id.tv_content);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send://发布事件
mTv_content.setText("对OneActivity发布事件");
//4.发布普通事件
EventBus.getDefault().post(new MessageEvent("接收到TwoActivity发送过来的事件啦"));
break;
default:
break;
}
}
}
3.2 粘性事件的使用
上面的普通事件中,订阅者(接收消息的页面OneActivity)要先注册,才能接收到发布的事件;也就是说接收消息的页面还没创建或者未注册订阅者,那么处理事件的方法根本无法接收发送者(发送消息页面TwoActivity)发布的事件。EventBus提供了一种粘性事件,能在发送事件之后再订阅该事件也能接收到该事件。与普通事件不同,普通事件是先注册后发布,粘性事件可以先发布后注册。
比如在项目中,在Activity1中发送事件到Activity2中做事件处理,如果Activity2没创建,那么是无法接收消息的,主要是Activity2用于接收消息的EventBus还没完成注册,即使发布了事件,订阅者还没产生,所以没法接收。
粘性事件的使用步骤和普通事件的使用步骤大致相同,不同的是发布和处理事件的方法:
(1)粘性事件的事件函数处理方法,需要在注解中添加sticky = true
标识,表示该事件是粘性事件:
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onStickyEvent(MessageEvent message) {
//TODO 接收事件后Do something
}
(2)使用postSticky()
发布粘性事件:
EventBus.getDefault().postSticky(Object event);
发布粘性事件后,EventBus将会一直存在粘性事件,在不需要粘性事件的时候需要及时移除,移除的方法有下面几个:
//移除指定的粘性事件
removeStickyEvent(Object event);
//移除指定对象类型的粘性事件
removeStickyEvent(Class<T> eventType);
//移除所有粘性事件
removeAllStickyEvents();
我们举个例子,创建两个Activity,在StickySendActivity中向StickyReceiveActivity发布粘性事件,发布完后跳转到StickyReceiveActivity中,StickyReceiveActivity创建并注册EventBus,订阅粘性事件的处理方法:
/**
* 发布粘性事件
*/
public class StickySendActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sticky_send);
findViewById(R.id.btn_send).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send://发布事件
//4.发布粘性事件
EventBus.getDefault().postSticky("StickySendActivity发送粘性事件");
startActivity(new Intent(this, StickyReceiveActivity.class));
break;
}
}
}
点击发送粘性事件按钮向StickyReceiveActivity发布粘性事件,发布完后跳转到StickyReceiveActivity中;
/**
* 注册并接收粘性事件
*/
public class StickyReceiveActivity extends AppCompatActivity{
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sticky_receive);
mTv_content = findViewById(R.id.tv_content);
//1.注册事件
EventBus.getDefault().register(this);
}
//3.接收StickySendActivity粘性事件处理, sticky = true表示是粘性事件
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onStickyEvent(String str) {
//TODO 接收事件后Do something
mTv_content.setText("onStickyEvent:接收到" + str);
Toast.makeText(this, "onStickyEvent:接收到" + str, Toast.LENGTH_SHORT).show();
EventBus.getDefault().removeStickyEvent(this)//移除粘性事件
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
}
StickyReceiveActivity创建并注册EventBus,订阅粘性事件的处理方法,接收到粘性事件发送的数据,显示在mTv_content控件上并吐司提示,然后通过removeStickyEvent(this)
移除当前的粘性事件。效果如下:
可以看到先发送粘性事件,后再注册处理事件也能接收到事件。
注意:发送事件的参数类型一定要与接收事件的参数类型一致,否则无法接收到事件的。
点关注,不迷路
好了各位,以上就是这篇文章的全部内容了,能看到这里的人呀,都是人才。
我是suming,感谢各位的支持和认可,您的点赞、评论、收藏【一键三连】就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !
要想成为一个优秀的安卓开发者,这里有必须要掌握的知识架构,一步一步朝着自己的梦想前进!Keep Moving!
相关文章:
EventBus3.2详解和使用(一)
● EventBus:普通事件和粘性事件的使用
EventBus3.2详解和使用(二)
● EventBus三要素、线程模式、优先级和AndroidEventBus的使用
EventBus3.2详解和使用(三)
● EventBus内部原理