Android事件总线1 EventBus3.2详解和使用

一 概述

EventBus 是适用于 Android 和 Java 的发布/订阅事件总线。主要功能是替代 Intent、Handler、BroadCast 在 Activity、Fragment、Service 线程之间传递消息。EventBus 能够简化应用组件间的通信,解耦 (有效分离) 事件的发送者和接收者,避免复杂和容易出错的依赖和生命周期问题,开销小,代码更优雅。但是需要注意的是 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 在接收到事件信息后,发送一个 Toast 并将接收的数据显示在屏幕上。
在这里插入图片描述
我们按照下面的步骤实现这个效果:

1.使用 EventBus 需要在 build.gradle 文件中添加依赖:
在这里插入图片描述
添加 EventBus3.2 依赖:

implementation 'org.greenrobot:eventbus:3.2.0'

2.定义事件对象

事件对象可以是任意 java 类型,比如 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 中的 post() 方法发布事件,参数为上面自定义的 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) 移除当前的粘性事件。效果如下:
在这里插入图片描述
可以看到先发送粘性事件,后再注册处理事件也能接收到事件。

注意:发送事件的参数类型一定要与接收事件的参数类型一致,否则无法接收到事件的。

有关 EventBus 深入理解和使用在下一篇Android事件总线2 EventBus3.2详解和使用讲解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EventBus是一个开源的发布/订阅事件总线库,它简化了不同组件之间的通信,避免了紧密耦合的代码。它使用了观察者模式,让不同的组件能够在没有直接关联的情况下相互通信。下面是EventBusAndroid中的使用详解。 1.导入EventBus库 在build.gradle文件中添加以下代码: ``` dependencies { implementation 'org.greenrobot:eventbus:3.2.0' } ``` 2.定义事件类 定义一个事件类,用于传递数据。 ```java public class MessageEvent { public final String message; public MessageEvent(String message) { this.message = message; } } ``` 3.注册EventBus 在需要接收事件的组件中注册EventBus。 ```java @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } ``` 4.注销EventBus 在不需要接收事件的组件中注销EventBus。 ```java @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } ``` 5.发布事件 在发送事件的组件中发布事件。 ```java EventBus.getDefault().post(new MessageEvent("Hello EventBus!")); ``` 6.订阅事件 在接收事件的组件中订阅事件。 ```java @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { String message = event.message; // 处理事件 } ``` 7.指定线程模式 EventBus支持在不同的线程中处理事件,可以通过@Subscribe注解的threadMode参数指定线程模式。 ```java @Subscribe(threadMode = ThreadMode.MAIN) // 主线程 public void onMessageEvent(MessageEvent event) { String message = event.message; // 处理事件 } @Subscribe(threadMode = ThreadMode.BACKGROUND) // 后台线程 public void onMessageEvent(MessageEvent event) { String message = event.message; // 处理事件 } @Subscribe(threadMode = ThreadMode.ASYNC) // 异步线程 public void onMessageEvent(MessageEvent event) { String message = event.message; // 处理事件 } ``` EventBus使用非常简单,但是需要注意以下几点: - 订阅方法必须使用@Subscribe注解,并且方法必须是public、void类型。 - 发布事件和接收事件的参数类型必须一致。 - 在注册EventBus时,不要忘记在onStop()方法中注销EventBus,否则可能会引起内存泄漏。 - EventBus默认在主线程中处理事件,如果事件处理需要耗时操作,可以使用不同的线程模式。 - EventBus不支持跨进程通信,只能在同一进程中的组件之间进行通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值