EventBus源码剖析(3) — 线程模式

栏目: IOS · Android · 发布时间: 6年前

内容简介:EventBus消息支持通过不同线程模式发送,以此满足注册类必须包含至少一个接收事件的方法Subscribe接口为修饰接收者的注解,

一、简介

EventBus消息支持通过不同线程模式发送,以此满足 Android 不同应用场景的需求。通过订阅者内的订阅方法可知,线程模式是通过注解参数进行配置

二、用法

注册类必须包含至少一个接收事件的方法

@Subscribe(threadMode = ThreadMode.MAIN, sticky = false, priority = 0)
fun onEventReceived(event: UserEvent) {
    val name = event.name
    val age = event.age
    Log.i(TAG, "Event received, Name: $name, Age: $age.")
}

三、类介绍

Subscribe接口为修饰接收者的注解, threadMode() 决定订阅者方法触发时所在的线程。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
    ThreadMode threadMode() default ThreadMode.POSTING;
    ....
    ....
}

EventBus支持的线程模式都保存在枚举类中。每个订阅者方法默认都定义一种线程模式,该模式告诉 EventBus 通过哪种线程去调用订阅者方法。

public enum ThreadMode

四、线程模式

ThreadMode枚举类中默认包含5种线程模式:

4.1 POSTING

订阅者在发布线程相同的线程上被调用,本模式是 EventBus 默认线程模式。因为完全避免线程切换,此线程模式的事件分发意味着能减少性能开销。

因此,对已知能在短时间内、主线程上完成的单个任务,本模式是首要推荐的。就是说此模式处理事件时,方法需要迅速执行完毕,并返回方法避免阻塞(主线程)发布线程。

POSTING,

4.2 MAIN

如果 EventBus 正在 Android 中使用,订阅者会在主线程中进行调用。如果消息发布线程就是主线程,则订阅者方法直接调用,并阻塞发布线程。否则,事件在消息队列等待主线程(非阻塞性的)分派。

由于接收者方法执行在主线程上,所以方法逻辑应轻巧,或在内部开启子线程执行重量级操作,以此避免阻塞主线程运行。推理可知,如果订阅者方法后续还有更多事件需要在主线程上发出,那么这些事件也会受到该次阻塞的影响。

如果 EventBus 所在环境不是 Android ,则本模式的执行行为和 POSTING 模式相同。

MAIN,

4.3 MAIN_ORDERED

Android 中订阅者方法也是在主线程中被调用。但和 MAIN 模式不同的,是本模式的消息会直接进入属于主线程的消息队列中排队等待执行,而不是阻塞主线程直接运行。

MAIN_ORDERED,

4.4 BACKGROUND

Android 中,此模式的订阅者会在后台线程调用。如果发布消息的线程不是主线程,则订阅者方法直接在发布线程上调用。如果消息发布线程是主线程, EventBus 会使用单个后台线程,该线程会顺序分派所有事件。如果订阅者使用此种模式,就应该快速从方法中返回,避免阻塞这个单一后台线程的运行。在非 Android 直接使用一个后台线程,不区分主线程。

BACKGROUND,

4.5 ASYNC

订阅者会在分离的线程上调用。此线程独立于事件发布线程和主线程。使用这种模式时,发送事件不会等待订阅者方法。可使用这个模式处理订阅者方法的耗时事件,例如:进行网络访问。为了避免同时触发大量、长期运行的订阅者方法, EventBus 使用了线程池,从已完成的异步订阅者通知复用线程。

ASYNC

实现

前文提到实现方法 EventBus.postToSubscription() 的逻辑就不难理解了。

private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
    // 获取订阅者方法指定线程的类别
    switch (subscription.subscriberMethod.threadMode) {
        case POSTING:
            invokeSubscriber(subscription, event);
            break;
        case MAIN:
            if (isMainThread) {
                // 处于主线程就直接触发订阅者
                invokeSubscriber(subscription, event);
            } else {
                // 处在其他线程,向主线程Handler发送消息
                mainThreadPoster.enqueue(subscription, event);
            }
            break;
        case MAIN_ORDERED:
            if (mainThreadPoster != null) {
                mainThreadPoster.enqueue(subscription, event);
            } else {
                // temporary: technically not correct as poster not decoupled from subscriber
                invokeSubscriber(subscription, event);
            }
            break;
        case BACKGROUND:
            if (isMainThread) {
                backgroundPoster.enqueue(subscription, event);
            } else {
                invokeSubscriber(subscription, event);
            }
            break;
        case ASYNC:
            asyncPoster.enqueue(subscription, event);
            break;

        // 传入未知threadMode,引起异常
        default:
            throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
    }
}

invokeSubscriber直接在消息发送者所在线程上调用目标方法。

void invokeSubscriber(Subscription subscription, Object event) {
    try {
        // subscription.subscriber:通过实例调用方法
        // event:调用时传递给方法的参数
        subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
    } catch (InvocationTargetException e) {
        // 捕获订阅者方法运行时异常,避免导致EventBus崩溃
        handleSubscriberException(subscription, event, e.getCause());
    } catch (IllegalAccessException e) {
        throw new IllegalStateException("Unexpected exception", e);
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

区块链核心算法解析

区块链核心算法解析

【瑞士】Roger Wattenhofer(罗格.瓦唐霍费尔) / 陈晋川、薛云志、林强、祝庆 / 电子工业出版社 / 2017-8 / 59.00

《区块链核心算法解析》介绍了构建容错的分布式系统所需的基础技术,以及一系列允许容错的协议和算法,并且讨论一些实现了这些技术的实际系统。 《区块链核心算法解析》中的主要概念将独立成章。每一章都以一个小故事开始,从而引出该章节的内容。算法、协议和定义都将以形式化的方式描述,以便于读者理解如何实现。部分结论会在定理中予以证明,这样读者就可以明白为什么这些概念或算法是正确的,并且理解它们可以确保实现......一起来看看 《区块链核心算法解析》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换