前言: 青春不是一个年纪的终结,也不是面孔的日益干瘪,而是永远有冲刺梦想的心情和挑战的勇气。
一、概述
EventBus是适用于Android和Java的发布/订阅事件总线。主要功能是替代Intent、Handler、BroadCast在Activity、Fragment、Service线程之间传递消息。EventBus能够简化应用组件间的通信,解耦(有效分离)事件的发送者和接收者,避免复杂和容易出错的依赖和生命周期问题,开销小,代码更优雅。
Andorid组件间通信,可能都是用Handler消息机制或者广播机制来实现通信,但是它们代码量大,组件上容易产生耦合 。为什么选择使用EventBus来做通信?
我们来看看EventBus的优点:
- 1、简化了组件间间的通信;
- 2、对事件通信双方进行解耦 ;
- 3、在Activity、Fragment和后台线程中能很好使用;
- 4、避免了复杂且容易出错的依赖性和生命周期问题 ;
- 5、可以灵活方便指定工作线程和优先级 ;
- 6、速度快,性能好,代码简单优雅;
- 7、库比较小,不占内存。
EventBus使用的是发布/订阅者模式:
发布者通过EventBus发布事件,订阅者通过EventBus订阅事件,当发布者发送事件时,订阅该事件的订阅者的事件处理方法将被调用。从图中看出,发布者发送一个事件时,则该事件将会同时传递给一个或多个该事件的订阅者。
1. 什么是发布/订阅者模式?
订阅者(Subscriber
)把自己想订阅的事件(Event
)注册(register
)到调度中心(EventBus
),当发布者(Publisher
)发布该事件到调度中心时,也就是该事件触发时,由调度中心统一调度订阅者注册到调度中心的处理代码(onEvent()
)。(发布/订阅者模式与观察者模式并不完全一样)
2. EventBus的三要素
- Event: 事件, 可以使任意类型;
- Publisher: 事件发布者,可以在任意线程中发布事件,一般情况,通过
EventBus.getDefault()
获取EventBus实例,通过post(Object event)
发布事件; - Subscriber: 事件订阅者,在EventBus3.0之前,订阅者的事件处理方法必须定义以onEvent开头的具体方法名,而在3.0之后方法名可以可以随意取,但是必须加上
@Subscribe()
注解,并且指定线程模式,默认为ThreadMode.POSTING
。
二、事件使用步骤
(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): 给订阅者注销事件的方法,如果事件不需要使用了必须调用该方法注销事件。
当消息页面不存在或者不需要事件了注销该事件。
三、项目实战
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;
}
}
}
复制代码
2. 粘性事件的使用
上面的普通事件中,订阅者要先注册,才能接收到发布的事件;也就是说接收消息的页面还没创建或者未注册订阅者,那么处理事件的方法根本无法接收发送者发布的事件。
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)
移除当前的粘性事件。效果如下:
可以看到先发送粘性事件,后再注册处理事件也能接收到事件。
注意:发送事件的参数类型一定要与接收事件的参数类型一致,否则无法接收到事件的。
四、 EventBus的几种线程模式
EventBus提供了几种线程模式,主要是为了发布事件和处理事件之间的线程切换使用。
线程模式 | 含义 | 特点 |
---|---|---|
1、POSTING | 默认线程,表示订阅者将在发布事件的同一线程中被调用 | 适用于不需要主线程就可以在短时间内完成的简单任务,避免了线程切换,开销更小 |
2、MAIN | 表示在Android中,订阅者在Android主线程中被调用 | 如果发布事件的线程是主线程,订阅者的事件处理函数将直接被调用。如果发布事件的线程不是主线程,则将事件加入主线程队列中,排队等待执行;因此这里不能进行耗时操作,注意不能阻塞主线程 |
3、MAIN_ORDERED | 表示在Android中,订阅者在Android主线程中被调用 | 与MAIN不同的是,无论发布事件的线程是在哪个线程,事件都将发送到主线程队列总是排队等待传递。注意不能阻塞主线程 |
4、BACKGROUND | 表示在Android中,订阅者在后台线程中被调用, | 在Android中,如果发布线程不是主线程,订阅者的事件处理函数直接使用该线程,如果发布线程是主线程,那么事件处理函数会开启一个后台线程,有序分发事件,注意不能阻塞后台线程,这里不能进行UI操作;如果不是在Android上,总是使用一个后台线程 |
5、ASYNC | 表示无论发布线程是什么线程,订阅者都会创建一个新的子线程执行 | 使用于耗时操作,尽量避免同时触发大量的耗时较长的异步操作,EventBus使用线程池高效的复用已经完成异步操作的线程 |
那么说明POSTING
模式的订阅者处理函数线程与发布线程一致,MAIN
和MAIN_ORDERED
模式的订阅者处理函数线程为主线程,BACKGROUND
和ASYNC
模式的订阅者处理函数线程为后台线程。
1. 几种线程模式使用
首先来验证一下不同的线程模式处理事件在哪个线程,创建两个Activity,ModeReceiveActivity中注册EventBus并且实现订阅者事件处理函数,ModeSendActivity负责发布事件。
/**
* 几种线程模式
* 注册并接收事件
*/
public class ModeReceiveActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "ModeReceiveActivity";
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mode_receive);
findViewById(R.id.btn_skip).setOnClickListener(this);
mTv_content = findViewById(R.id.tv_content);
//1.注册事件
EventBus.getDefault().register(this);
}
//3.订阅者的接收事件处理函数
//处理函数执行线程与发布线程一致
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEventPosting(String str) {
//TODO 接收事件后Do something
mTv_content.setText("onMessageEvent:" + str);
Log.e(TAG, "onMessageEventPosting:" + Thread.currentThread().getName());
}
//处理函数执行线程为主线程
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMain(String str) {
Log.e(TAG, "onMessageEventMain:" + Thread.currentThread().getName());
}
//处理函数执行线程为主线程
@Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
public void onMessageEventMainOrdered(String str) {
Log.e(TAG, "onMessageEventMainOrdered:" + Thread.currentThread().getName());
}
//处理函数执行线程为后台线程
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEventBackground(String str) {
Log.e(TAG, "onMessageEventBackground:" + Thread.currentThread().getName());
}
//处理函数执行线程为后台线程
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEventAsync(String str) {
Log.e(TAG, "onMessageEventAsync:" + Thread.currentThread().getName());
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_skip://跳转到ModeSendActivity
startActivity(new Intent(this, ModeSendActivity.class));
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
}
复制代码
ModeReceiveActivity作为接受消息的页面,是订阅者,首先在在onCreate()
注册EventBus,onDestroy()
中反注册,并且实现几种线程模式的订阅者的事件处理函数,将接收数据的线程通过Thread.currentThread().getName()
线程名字打印log,点击按钮跳转到ModeSendActivity发布者中在主线程发布事件。
/**
* 几种线程模式
* 发送事件
*/
public class ModeSendActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mode_send);
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("对ModeReceiveActivity发布事件");
//4.发布事件
EventBus.getDefault().post("接收到ModeSendActivity发送过来的事件啦");
break;
}
}
}
复制代码
点击发布事件按钮ModeSendActivity给ModeReceiveActivity发送事件,这里发布的线程是主线程。打印数据如下:
可以看到,POSTING
模式的线程与发布线程一致,都是主线程;MAIN
和MAIN_ORDERED
模式的线程为主线程,BACKGROUND
和ASYNC
模式线程为后台线程。
2. 事件的优先级
EventBus支持定义订阅者事件处理方法时指定事件传递的优先级。默认情况下,事件优先级为0,数值越大,优先级越高,在相同线程模式下,优先级高的比优先级低的先接收到事件。
注意:优先级只有在相同线程模式下才有效。
@Subscribe(threadMode = ThreadMode.MAIN, priority = 0)
public void onMessageEvent(String str) {
//TODO 接收事件后Do something
}
复制代码
- priority : 事件优先级, int类型,默认为0;数值越大,优先级越高,在相同线程模式下,优先级高的比优先级低的先接收到事件。
我们来创建两个Activity检验一下,PriorityReceiveActivity实现订阅者的事件处理方法,不同优先级的多个方法,PrioritySendActivity负责发布事件。
PriorityReceiveActivity.java
/**
* 事件优先级
* 注册并接收事件
*/
public class PriorityReceiveActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "PriorityReceiveActivity";
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_priority_receive);
findViewById(R.id.btn_skip).setOnClickListener(this);
mTv_content = findViewById(R.id.tv_content);
//1.注册事件
EventBus.getDefault().register(this);
}
//3.订阅者的接收事件处理函数, 事件优先级0,1,2
@Subscribe(threadMode = ThreadMode.MAIN, priority = 0)
public void onMessageEvent(String str) {
//TODO 接收事件后Do something
mTv_content.setText("onMessageEvent:" + str);
Log.e(TAG, "onMessageEvent:priority = 0 " + str);
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = 1)
public void onMessageEvent1(String str) {
Log.e(TAG, "onMessageEvent:priority = 1 "+str);
}
@Subscribe(threadMode = ThreadMode.MAIN, priority = 2)
public void onMessageEvent2(String str) {
Log.e(TAG, "onMessageEvent:priority = 2 " + str);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_skip://跳转到PrioritySendActivity
startActivity(new Intent(this, PrioritySendActivity.class));
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
}
复制代码
这里定义了priority = 0,1,2三个优先级的处理函数,在onCreate()
注册EventBus,onDestroy()
中反注册,点击按钮跳转到PrioritySendActivity中;
/**
* 事件优先级
* 发送事件
*/
public class PrioritySendActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_priority_send);
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("对PriorityReceiveActivity发布事件");
//4.发布事件
EventBus.getDefault().post("接收到PrioritySendActivity发送过来的事件啦");
break;
}
}
}
复制代码
点击发布事件按钮,给PriorityReceiveActivity发布事件,接收到数据,效果如下:
打印log如下:
从数据可以看到,优先级priority = 0<1<2,优先级高的比优先级低的先接收到数据。
五、AndroidEventBus的使用
发布者发送一个事件时,则该事件将会同时传递给一个或多个该事件的订阅者。如果发布事件的事件对象类型与订阅者处理事件方法对象类型匹配,那么匹配的所有已注册的事件都会接收到。
//发布事件
EventBus.getDefault().post(new MessageEvent());
//多个接收事件处理的函数
//接收Activity1事件处理
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventActivity1(MessageEvent message) {
//TODO 接收事件后Do something
Log.e(TAG, "onMessageEventActivity1 ==");
}
//接收Activity2事件处理
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventActivity2(MessageEvent message) {
//TODO 接收事件后Do something
Log.e(TAG, "onMessageEventActivity2 ==");
}
复制代码
onMessageEventActivity1()
和onMessageEventActivity2()
都在同一个Activity中订阅事件,但是发布者来自不同的Activity,发布事件post(Object event)
方法中的event的类型与处理事件onMessageEvent(Object event)
中event的类型一致的话,都会接收到发布的数据。打印数据如下:
当然我们可以指定不同的事件对象类型,或者在事件对象类型添加标志区分,比如在MessageEvent中添加type区分不同。但是如果都是事件对象类型都是String那就区分不了。
1. AndroidEventBus
我们可以使用AndroidEventBus,EventBus是AndroidEventBus框架的核心类,也是用户的入口类。它存储了用户注册的订阅者信息和方法,事件类型和该事件对应的tag标识一个种类的事件EventType,每一种事件对应有一个或者多个订阅者,订阅者中的订阅函数通过@Subscriber
注解来标识tag和线程模型,这样使得用户体检较为友好,代码也更加整洁。
AndroidEventBus与EventBus不同的是,多了一种该事件对应的tag标识和订阅者中的订阅函数通过@Subscriber
注解(EventBus的是@Subscribe)。
//发布者发布事件,tag为from_three
EventBus.getDefault().post(new MessageEvent("接收到AndroidBusSendActivity发送过来的事件啦"), "from_three");
//订阅者的事件处理函数, 有tag为from_three
@Subscriber(tag = "from_three", mode = ThreadMode.MAIN)
public void eventAndroidEventBus(MessageEvent message) {
}
复制代码
- post(Object event, String tag): 发布者发布事件的方法;event表示要发布的事件,任意类型;tag表示事件的标识,用于区分其他事件,String类型(区分大小写);
- @Subscriber:必须使用@Subscriber注解来定义订阅者方法,否则事件处理方法无法生效。与EventBus的@Subscribe类同;
- tag : tag表示事件的标识,用于区分其他事件。与发布事件的tag相对应;
- mode : 线程模式,表示在哪个线程里面执行。与EventBus的threadMode类同。
2. AndroidEventBus普通事件
AndroidEventBus与EventBus的用法大致相同,首先在build.gradle文件中添加依赖:
implementation 'org.simple:androideventbus:1.0.5.1'
复制代码
然后创建两个Activity,AndroidBusSendActivity发布者发布事件,AndroidBusReceiveActivity在onCreate()
和onDestroy()
中注册反注册事件,实现不同tag的多个订阅者事件处理方法。
注意,需要使用AndroidEventBus的包org.simple.eventbus
import org.simple.eventbus.EventBus;
import org.simple.eventbus.Subscriber;
import org.simple.eventbus.ThreadMode;
/**
* AndroidEventBus
* 接收消息页面
*/
public class AndroidBusReceiveActivity extends AppCompatActivity implements View.OnClickListener{
public static final String TAG = "AndroidEventBus";
private TextView mTv_content, mTv_content2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_receive);
findViewById(R.id.btn_skip).setOnClickListener(this);
mTv_content = findViewById(R.id.tv_content);
mTv_content2 = findViewById(R.id.tv_content2);
//1.注册事件
EventBus.getDefault().register(this);
}
//3.接收事件处理, 有tag为from_three
@Subscriber(tag = "from_three", mode = ThreadMode.MAIN)
public void eventAndroidEventBus(MessageEvent message) {
mTv_content2.setText("eventAndroidEventBus: tag = from_three | " + message.name);
Log.e(TAG, "eventAndroidEventBus == tag = from_three | " + message.name);
}
//接收事件处理,有tag为FROM_THREE
@Subscriber(tag = "FROM_THREE", mode = ThreadMode.MAIN)
public void eventAndroidEventBus1(MessageEvent message) {
mTv_content.setText("eventAndroidEventBus: tag = FROM_THREE | " + message.name);
Log.e(TAG, "eventAndroidEventBus1 == tag = FROM_THREE | " + message.name);
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
}
复制代码
import org.simple.eventbus.EventBus;
/**
* AndroidEventBus
* 发送消息页面
*/
public class AndroidBusSendActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_send);
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("对AndroidBusReceiveActivity发布事件");
//4.发布事件,tag为from_three
EventBus.getDefault().post(new MessageEvent("接收到AndroidBusSendActivity发送过来的事件啦"), "from_three");
break;
default:
break;
}
}
}
复制代码
效果如下:
打印数据如下:
可以看到,即使事件类型一致,但是只有发布事件和订阅函数处理的tag相同才能接收到事件。
3. AndroidEventBus的粘性事件
粘性事件能在发送事件之后再订阅该事件也能接收到该事件。与普通事件不同,普通事件是先注册后发布,粘性事件可以先发布后注册。
AndroidEventBus的粘性事件的使用与EventBus的粘性事件不同,AndroidEventBus需要注册粘性事件,订阅者的事件处理函数不需要添加sticky标识。来看看AndroidEventBus的粘性事件的使用步骤:
(1) 在onCreate()
中注册粘性事件registerSticky()
,onDestroy()
中反注册事件。
@Override
protected void onCreate(Bundle savedInstanceState) {
//1.注册粘性事件
EventBus.getDefault().registerSticky(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
复制代码
(2) 订阅者的事件处理函数。
//3.接收粘性事件处理, 有tag为from_android_sticky
@Subscriber(tag = "from_android_sticky", mode = ThreadMode.MAIN)
public void eventAndroidEventBus(String message) {
Log.e(TAG, "eventAndroidEventBus == tag = from_android_sticky | " + message);
//5.移除粘性事件
EventBus.getDefault().removeStickyEvent(String.class, "from_android_sticky");
}
复制代码
注意:如果不需要粘性事件了通过抽象removeStickyEvent()
及时移除粘性事件。
(3) 发布者发布粘性事件postSticky()
。
//4.发布粘性事件,tag为from_android_sticky
EventBus.getDefault().postSticky("接收到AndroidStickySendActivity发送过来的事件啦", "from_android_sticky");
复制代码
我们创建两个Activity,AndroidStickySendActivity先布粘性事件然后再跳转AndroidStickyReceiveActivity,AndroidStickyReceiveActivity创建并注册EventBus后接收到粘性事件消息。
/**
* AndroidEventBus粘性事件
* 发送消息页面
*/
public class AndroidStickySendActivity extends AppCompatActivity implements View.OnClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_send_sticky);
findViewById(R.id.btn_send).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_send://发布事件
//4.发布粘性事件,tag为from_three
EventBus.getDefault().postSticky("接收到AndroidStickySendActivity发送过来的事件啦", "from_android_sticky");
startActivity(new Intent(this, AndroidStickyReceiveActivity.class));
break;
}
}
}
复制代码
AndroidStickySendActivity中点击发布粘性事件按钮,给AndroidStickyReceiveActivity发送事件,再跳转到AndroidStickyReceiveActivity中。
/**
* AndroidEventBus粘性事件
* 接收消息页面
*/
public class AndroidStickyReceiveActivity extends AppCompatActivity {
public static final String TAG = "StickyReceiveActivity";
private TextView mTv_content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_receive_sticky);
mTv_content = findViewById(R.id.tv_content);
//1.注册粘性事件
EventBus.getDefault().registerSticky(this);
}
//3.接收粘性事件处理, 有tag为from_three
@Subscriber(tag = "from_android_sticky", mode = ThreadMode.MAIN)
public void eventAndroidEventBus(String message) {
mTv_content.setText("eventAndroidEventBus == tag = from_android_sticky | " + message);
Log.e(TAG, "eventAndroidEventBus == tag = from_android_sticky | " + message);
//5.移除粘性事件
EventBus.getDefault().removeStickyEvent(String.class, "from_android_sticky");
}
@Override
protected void onDestroy() {
super.onDestroy();
//2.反注册事件
EventBus.getDefault().unregister(this);
}
}
复制代码
AndroidStickyReceiveActivity完成创建并注册EventBus,实现订阅者的粘性事件处理方法,接收到发送过来的粘性事件数据,效果如下:
打印数据如下:
注意:发送事件的参数类型一定要与接收事件的参数类型一致啊,否则无法接收到事件的。
点关注,不迷路
好了各位,以上就是这篇文章的全部内容了。非常感谢您阅读这篇文章,能看到这里的都是人才。我是suming,感谢各位的支持和认可,您的点赞就是我创作的最大动力,我们下篇文章见!
如果本篇博客有任何错误,请批评指教,不胜感激 !