EventBus 实战详解

前言: 青春不是一个年纪的终结,也不是面孔的日益干瘪,而是永远有冲刺梦想的心情和挑战的勇气。

一、概述

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模式的订阅者处理函数线程与发布线程一致,MAINMAIN_ORDERED模式的订阅者处理函数线程为主线程,BACKGROUNDASYNC模式的订阅者处理函数线程为后台线程

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模式的线程与发布线程一致,都是主线程;MAINMAIN_ORDERED模式的线程为主线程,BACKGROUNDASYNC模式线程为后台线程。

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,感谢各位的支持和认可,您的点赞就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享