内容简介: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);
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【重回基础】线程池源码剖析:Worker工作线程
- 线程池的使用和源码剖析
- Java线程池ThreadPoolExecutor实现原理剖析
- Java 多线程并发读写锁 ReadWriteLock 实现原理剖析
- MySQL(InnoDB剖析):05---InnoDB体系架构(后台线程、内存池、文件)
- 【Java集合源码剖析】ArrayList源码剖析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
算法设计、分析与实现
徐子珊 / 2012-10 / 65.00元
《算法设计、分析与实现:c、c++和java》由徐子珊编著,第1章~第6章按算法设计技巧分成渐增型算法、分治算法、动态规划算法、贪婪算法、回溯算法和图的搜索算法。每章针对一些经典问题给出解决问题的算法,并分析算法的时间复杂度。这样对于初学者来说,按照算法的设计方法划分,算法思想的阐述比较集中,有利于快速入门理解算法的精髓所在。一旦具备了算法设计的基本方法,按应用领域划分专题深入学习,读者可以结合已......一起来看看 《算法设计、分析与实现》 这本书的介绍吧!
随机密码生成器
多种字符组合密码
html转js在线工具
html转js在线工具