【Android】EventBus事件总线用法浅析

【Android】EventBus事件总线用法浅析

EventBus 是一个基于发布-订阅模式的 Android 库,专注于简化组件之间的通信。提供了一种高效、灵活且解耦的方式,用于在应用程序的不同组件(如 Activity、Fragment、Service 等)之间传递消息或事件。比如请求网络,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。

EventBus 的核心功能

  • 解耦组件:
    发布者和订阅者之间不需要直接引用,降低了耦合性。
  • 跨线程通信:
    可以指定事件处理在哪个线程执行(主线程、后台线程等)。
  • 事件优先级:
    支持设置订阅者的优先级,以决定事件处理的先后顺序。

EventBus使用方法

首先来看看EventBus的三要素!

1. Event(事件)

定义:事件是消息传递的载体,可以是任意类型的对象,例如自定义的类、基本数据类型的包装类等。

作用:用来承载需要传递的数据。

使用方式:开发者可以根据需求自定义事件类,携带需要传递的信息。

public class MessageEvent {
   
    public final String message;

    public MessageEvent(String message) {
   
        this.message = message;
    }
}
Subscriber(订阅者)

定义:订阅者是接收事件的对象。在 EventBus 中,订阅者需要通过注解 @Subscribe 标记特定的方法来订阅事件。

注意:EventBus 3.0 之前,订阅的方法名称必须是固定的(如 onEventonEventMainThread 等),而 3.0 之后方法名可以自定义,只需用 @Subscribe 注解即可。

订阅者需要指定线程模型,默认是 POSTING 模式。

Publisher(发布者)

定义:事件发布者是负责发送事件的组件,可以是应用中的任意部分。

作用:将事件发送到事件总线,由总线分发给匹配的订阅者。

使用方式:通过调用 EventBus.getDefault().post(Object) 发送事件。

EventBus.getDefault().post(new MessageEvent("Hello EventBus!"));

再来看看 EventBus 的 4 种 ThreadMode 线程模型!

POSTING(默认):如果使用事件处理函数指定了线程模型为POSTING,那么该事件是在哪个线程发布出来的,事件处理函数就会在哪个线程中运行,也就是说发送事件和接收事件在同一个线程中。在线程模型为POSTING的事件处理函数中尽量避免执行耗时操作,因为它会阻塞事件的传递,甚至有可能会引起ANR(Application Not Responding)问题。

MAIN:事件的处理会在切线程中执行。事件处理的时间不能太长,长了会引起ANR问题。

BACKGROUND:如果事件是在U线程中发布出来的,那么该事件处理函数就会在新的线程中运行;如果事件本来就是在子线程中发布出来的,那么该事件处理函数直接在发送事件的线程中执行。在此事件处理函数中禁止进行UI更新操作。

ASYNC:无论事件在哪个线程中发布,该事件处理函数都会在新建的子线程中执行,同样,此事件处理函数中禁止进行UI更新操作。

EventBus 基本用法

EventBus 使用起来分为以下 5 个步骤:

(1)自定义一个事件类

public class MessageEvent {
   
    ...
}

(2)在需要订阅事件的地方注册事件

EventBus.getDefault().register(this);

(3)发送事件

EventBus.getDefault().post(messageEvent);

(4)处理事件

@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
   
    ...
}

(5)取消事件订阅

EventBus.getDefault().unregister(this);

EventBus 的黏性事件

黏性事件(Sticky Event) 是 EventBus 提供的一种特殊事件传递机制,即在事件发送之后,即使没有订阅该事件,稍后订阅者也能接收到这个事件。主要用于处理订阅发生在事件发布之后的场景。

黏性事件的原理

当使用 postSticky() 方法发布事件时,EventBus 会将该事件保存到内部的缓存中(StickyEvent Map)。当订阅者订阅时,会立即检查是否有符合条件的黏性事件,如果有则立即分发给订阅者。这种机制特别适合需要保存全局状态或后续动态注册的场景。

详细实现步骤

1. 定义事件类
public class MessageEvent {
   
    private String message;

    public MessageEvent(String message) {
   
        this.message = message;
    }

    public String getMessage() {
   
        return message;
    }
}
2. 订阅黏性事件

MainActivity 中定义一个处理黏性事件的方法,并用 @Subscribe 注解标记,同时指定 sticky = true

@Subscribe(threadMode = ThreadMode.POSTING, sticky = true)
public void onStickyEvent(MessageEvent messageEvent) {
   
    tv_message.setText(messageEvent.getMessage());
}

threadMode = ThreadMode.POSTING:订阅者运行在事件发布的线程。

sticky = true:表示该方法订阅的是黏性事件。

@Override
protected void onStart() {
   
    super.onStart();
    EventBus.getDefault().register(this); // 注册订阅者
}

@Override
protected void onStop() {
   
    super.onStop();
    EventBus.getDefault().unregister(this); // 注销订阅者
}
3. 发布黏性事件

SecondActivity 中,通过 postSticky() 方法发布黏性事件:

bt_subscription.setOnClickListener(new View.OnClickListener() {
   
    @Override
    public void onClick(View v) {
   
        EventBus.getDefault().postSticky(new MessageEvent("黏性事件"));
        finish(); // 返回到 MainActivity
    }
});

MainActivity 中不要立即注册订阅者(不点击“注册事件”按钮)。

跳转到 SecondActivity 并点击“发送黏性事件”按钮,这会发布一个黏性事件并返回到 MainActivity

回到 MainActivity,点击“注册事件”按钮,这时订阅方法会接收到之前发送的黏性事件,更新界面内容。

EventBus使用示例

你是西安邮电大学的一名正在学习安卓的带学生,此时你需要开发一个应用,其中包含如下内容:

  1. 登录页面: 用户输入账号和密码,点击登录。
  2. 首页: 显示用户的个性化内容,如推荐文章、好友动态等。
  3. 个人中心: 显示用户的昵称、头像和其他信息。

当用户成功登录后,首页和个人中心需要同时刷新数据以展示用户的最新状态。例如,首页需要显示用户的推荐内容,个人中心需要更新用户的昵称和头像。


常规实现的问题
  1. 接口直接调用: 登录成功后,直接调用首页和个人中心的刷新接口。这种方法需要登录页面直接依赖首页和个人中心的逻辑,导致强耦合。
  2. 广播机制: Android 的广播可以用来解决,但实现过程较复杂,还需要注册和过滤广播。

用 EventBus 实现
  1. 解耦: 登录页面不需要知道首页和个人中心的具体实现,只需发布一个登录成功的事件。
  2. 异步处理: 首页和个人中心可以根据需要选择在主线程或后台线程中处理事件。

实现步骤

1. 定义事件类

创建一个表示用户登录成功的事件:

public class LoginSuccessEvent {
   
    private final String userId;

    public LoginSuccessEvent(String userId) {
   
        this.userId = userId;
    }

    public String getUserId() {
   
        return userId;
    }
}
2. 发布事件

在登录成功的逻辑中,发布事件通知其他组件:

// 假设登录成功后获取到用户ID
String userId = "12345";
EventBus.getDefault().post(new LoginSuccessEvent(userId));
3. 订阅事件

在需要响应登录成功事件的页面(如首页和个人中心),订阅事件:

首页代码:

@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginSuccess(LoginSuccessEvent event) {
   
    // 刷新推荐内容
    refreshContent(event.getUserId());
}

@Override
protected void onStart(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值