EventBus

概述

EventBus是一款针对Android优化的发布/订阅(publish/subscribe)事件总线。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,线程之间传递消息。简化了应用程序内各组件间、组件与后台线程间的通信。优点是开销小,代码更优雅。以及将发送者和接收者解耦。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。

EventBus作为一个消息总线,有三个主要的元素:

  • Event:事件。可以是任意类型的对象
  • Subscriber:事件订阅者,接收特定的事件。在EventBus中,使用约定来指定事件订阅者以简化使用。即所有事件订阅都都是以onEvent开头的函数,具体来说,函数的名字是onEvent,onEventMainThread,onEventBackgroundThread,onEventAsync这四个,这个和 ThreadMode(下面讲)有关。
  • Publisher:事件发布者,用于通知 Subscriber 有事件发生。可以在任意线程任意位置发送事件,直接调用eventBus.post(Object) 方法,可以自己实例化 EventBus 对象,但一般使用默认的单例就好了:EventBus.getDefault(), 根据post函数参数的类型,会自动调用订阅相应类型事件的函数。

关于ThreadMode

前面说了,Subscriber的函数只能是那4个,因为每个事件订阅函数都是和一个ThreadMode相关联的,ThreadMode指定了会调用的函数。有以下四个ThreadMode:

  • PostThread:事件的处理在和事件的发送在相同的进程,所以事件处理时间不应太长,不然影响事件的发送线程,而这个线程可能是UI线程。对应的函数名是onEvent。
  • MainThread: 事件的处理会在UI线程中执行。事件处理时间不能太长,这个不用说的,长了会ANR的,对应的函数名是onEventMainThread。
  • BackgroundThread:事件的处理会在一个后台线程中执行,对应的函数名是onEventBackgroundThread,虽然名字是BackgroundThread,事件处理是在后台线程,但事件处理时间还是不应该太长,因为如果发送事件的线程是后台线程,会直接执行事件,如果当前线程是UI线程,事件会被加到一个队列中,由一个线程依次处理这些事件,如果某个事件处理时间太长,会阻塞后面的事件的派发或处理。
  • Async:事件处理会在单独的线程中执行,主要用于在后台线程中执行耗时操作,每个事件会开启一个线程(有线程池),但最好限制线程的数目。

根据事件订阅都函数名称的不同,会使用不同的ThreadMode,比如果在后台线程加载了数据想在UI线程显示,订阅者只需把函数命名onEventMainThread。

对相应的函数名,进一步解释一下:

onEvent:如果使用onEvent作为订阅函数,那么该事件在哪个线程发布出来的,onEvent就会在这个线程中运行,也就是说发布事件和接收事件线程在同一个线程。使用这个方法时,在onEvent方法中不能执行耗时操作,如果执行耗时操作容易导致事件分发延迟。

onEventMainThread:如果使用onEventMainThread作为订阅函数,那么不论事件是在哪个线程中发布出来的,onEventMainThread都会在UI线程中执行,接收事件就会在UI线程中运行,这个在Android中是非常有用的,因为在Android中只能在UI线程中跟新UI,所以在onEvnetMainThread方法中是不能执行耗时操作的。

onEventBackground:如果使用onEventBackgrond作为订阅函数,那么如果事件是在UI线程中发布出来的,那么onEventBackground就会在子线程中运行,如果事件本来就是子线程中发布出来的,那么onEventBackground函数直接在该子线程中执行。

onEventAsync:使用这个函数作为订阅函数,那么无论事件在哪个线程发布,都会创建新的子线程在执行onEventAsync。

基本用法

引入EventBus:

compile 'org.greenrobot:eventbus:3.0.0'

定义事件:

public class MessageEvent { /* Additional fields if needed */ }

注册事件接收者:

eventBus.register(this);

发送事件:

eventBus.post(event)

接收消息并处理:

// 3.0后不再要求事件以 onEvent 开头,而是采用注解的方式
@Subscribe(threadMode = ThreadMode.MAIN)
public void receive(MessageEvent event){}

注销事件接收:

eventBus.unregister(this);

索引加速:

3.0 后引入了索引加速(默认不开启)的功能,即通过 apt 编译插件的方式,在代码编译的时候对注解进行索引,避免了以往通过反射造成的性能损耗。
如何使用可以参考[官方文档](http://greenrobot.org/eventbus/documentation/subscriber-index/)

最后,proguard 需要做一些额外处理:

#EventBus
 -keepclassmembers class ** {
    public void onEvent*(**);
    void onEvent*(**);
 }

 

### EventBus 在编程中的使用和实现 EventBus 是一种用于简化事件驱动架构的工具,它允许组件之间通过发布-订阅模式进行通信。以下是关于 EventBus 的详细信息以及其实现方式: #### 什么是 EventBusEventBus 是一种设计模式的实现,通常用于解耦发布者和订阅者之间的直接依赖关系。它允许一个或多个订阅者监听特定类型的事件,并在这些事件发生时执行相应的操作[^1]。 #### EventBus 的主要特性 - **发布-订阅模式**:发布者将事件发送到总线,而订阅者从总线接收事件。 - **解耦**:发布者不需要知道哪些订阅者会处理事件,反之亦然。 - **异步支持**:某些实现允许事件以异步方式处理,从而提高性能。 #### 常见的 EventBus 实现 以下是一些常见的 EventBus 库及其用法示例: ##### 1. Guava EventBus Google 提供的 Guava 库中包含了一个简单的 EventBus 实现。 ```java // 创建 EventBus 实例 EventBus eventBus = new EventBus(); // 定义事件处理器 public class MyEventHandler { @Subscribe public void handleMyEvent(MyEvent event) { System.out.println("Received event: " + event.getMessage()); } } // 发布事件 eventBus.register(new MyEventHandler()); eventBus.post(new MyEvent("Hello, EventBus!")); ``` ##### 2. Vert.x EventBus Vert.x 是一个基于 JVM 的工具包,支持分布式事件总线。 ```java // 创建 Vert.x 实例 Vertx vertx = Vertx.vertx(); // 注册消息处理器 vertx.eventBus().consumer("my.address", message -> { System.out.println("Received message: " + message.body()); }); // 发送消息 vertx.eventBus().send("my.address", "Hello from Vert.x!"); ``` ##### 3. Otto (现已停止维护) Otto 是 Square 公司开发的一个轻量级事件总线库。 ```java // 创建 EventBus 实例 Bus bus = new Bus(); // 定义事件处理器 public class MySubscriber { @Subscribe public void handleMessage(MyEvent event) { System.out.println("Received message: " + event.message); } } // 注册订阅者并发布事件 bus.register(new MySubscriber()); bus.post(new MyEvent("Hello, Otto!")); ``` #### 使用场景 - **UI 事件处理**:在 GUI 应用程序中,EventBus 可以用来解耦视图和控制器。 - **微服务通信**:在微服务架构中,EventBus 可以作为服务间通信的一种方式[^2]。 - **插件系统**:在需要动态加载模块的系统中,EventBus 可以帮助模块之间进行松散耦合的通信。 #### 注意事项 - **性能问题**:对于高频率的事件,EventBus 可能会导致性能下降。 - **调试困难**:由于发布者和订阅者之间没有直接联系,调试可能会变得复杂。 - **内存泄漏**:未正确注销的订阅者可能导致内存泄漏。 ```python # 示例:Python 中的简单 EventBus 实现 class EventBus: def __init__(self): self.subscribers = {} def subscribe(self, event_type, handler): if event_type not in self.subscribers: self.subscribers[event_type] = [] self.subscribers[event_type].append(handler) def publish(self, event_type, event): if event_type in self.subscribers: for handler in self.subscribers[event_type]: handler(event) # 使用示例 def handle_event(event): print(f"Handling event: {event}") bus = EventBus() bus.subscribe('my_event', handle_event) bus.publish('my_event', 'Hello, Python EventBus!') ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值