EventBus(观察者模式的实现)

注意:这里的 EventBus 并不是 Google Guava 工具库中的 EventBus,而是一个单独的 EventBus 项目

github:https://github.com/greenrobot/EventBus

使用 EventBus 仅需三步

  1. 定义事件消息类
public static class MessageEvent { /* Additional fields if needed */ }
  1. 定义事件消息的处理函数
@Subscribe(threadMode = ThreadMode.MAIN)  
public void onMessageEvent(MessageEvent event) {
    // Do something
}

注册或取消注册事件处理函数

// 注册事件处理函数
EventBus.getDefault().register(new Object());
// 取消注册事件处理函数
EventBus.getDefault().unregister(new Object());
  1. 发送事件消息
EventBus.getDefault().post(new MessageEvent());

测试代码

添加依赖 jar

        <dependency>
            <groupId>org.greenrobot</groupId>
            <artifactId>eventbus-java</artifactId>
            <version>3.3.1</version>
        </dependency>

EventBusDemo.java

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.EventBusBuilder;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

public class EventBusDemo {
    // 1. 创建消息类
    private static class MessageEvent {
        private String message;

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

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

    // 2. 创建事件处理函数,需要使用 @Subscribe 进行注解
    @Subscribe(threadMode = ThreadMode.ASYNC)
    public void onMessageEvent(MessageEvent msg) {
        System.out.println("接收消息" + msg.getMessage());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("处理消息" + msg.getMessage());
    }


    public static void main(String[] args) {
        // 3. 创建 EventBus 对象 -- 直接使用 EventBus.getDefault() 获取单例实现

        // 4. 注册监听者类
        EventBus.getDefault().register(new EventBusDemo());
        // 5. 发布消息
        for (int i=0; i<5; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("---------");
            EventBus.getDefault().post(new MessageEvent("tttt" + i));
        }
    }
}

执行输出如下:

---------
接收消息tttt0
---------
接收消息tttt1
---------
接收消息tttt2
---------
接收消息tttt3
---------
接收消息tttt4
处理消息tttt0
处理消息tttt1
处理消息tttt2
处理消息tttt3
处理消息tttt4

可以看到实现了事件消息的并发执行。

@Subscribe 注解的说明

事件消息的处理函数必须使用 @Subscribe 进行注解,该注解源码及属性值的设置说明如下:


@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    /**
     * 事件消息执行时的线程模式,默认为 POSTING
     * 1. POSTING 事件处理函数将与事件发布在同一线程内运行。事件传递开销最小,避免了线程切换,适用于已知的可以在很短时间内完成而不需要主线程参与的简单任务。
     *     主线程发布事件消息:在主线程进行事件消息的处理
     *     子线程发布事件消息:在子线程进行事件消息的处理
     * 2. MAIN 如果是在 Android 设备上,在主线程进行事件消息的处理,适用于在很短时间内完成的任务,以避免阻塞主线程。在非 Android 设备上与 POSTING 逻辑一致。
     *     主线程发布事件消息:立即进行事件处理,并会阻塞主线程执行
     *     子线程发布事件消息:时间在队列中排队等待主线程执行,不会阻塞发布线程
     * 3. MAIN_ORDERED 类似 MAIN 模式,事件会被主线程处理,但如果事件消息是在主线程发出,则也会排队等待,不会阻塞主线程执行
     * 4. BACKGROUND 事件消息会在子线程执行
     *     主线程发布事件消息:将事件消息加入队列,然后等待线程池执行
     *     子线程发布事件消息:直接在事件发布的线程执行,并会阻塞发布线程
     * 5. ASYNC 无论在哪个线程发布的事件,都会被放入队列,通过线程池执行事件
     */
    ThreadMode threadMode() default ThreadMode.POSTING;

    /**
     * If true, delivers the most recent sticky event (posted with
     * {@link EventBus#postSticky(Object)}) to this subscriber (if event available).
     */
    boolean sticky() default false;

    /** Subscriber priority to influence the order of event delivery.
     * Within the same delivery thread ({@link ThreadMode}), higher priority subscribers will receive events before
     * others with a lower priority. The default priority is 0. Note: the priority does *NOT* affect the order of
     * delivery among subscribers with different {@link ThreadMode}s! */
    int priority() default 0;
}
posted @ 2022-11-01 11:16  杰哥不是大哥  阅读(120)  评论(0)    收藏  举报