EventBus源码分析(三):Subscribe注解详解
前面把EventBus源码看了一遍,回头再看一下EventBus初步使用一文中提到的Subscribe注解,就会更加理解这其中三个属性的含义及作用:
@Subscribe(threadMode = ThreadMode.BACKGROUND, sticky = true, priority = 100)
public void onEvent(MessageEvent messageEvent) {
//textView.setText(messageEvent.message);
}
1、Subscribe注解
Subscribe注解定义如下:Subscribe注解只能作用在方法上;在编译后不仅被保留,在运行时获取该注解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Subscribe {
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;
}
Subscribe注解有三个属性:
①threadMode:执行订阅方法的线程模型。默认POSTING,在事件发送线程执行订阅方法。
②sticky:sticky属性默认false,订阅方法不接受粘性事件。
③priority:订阅方法的优先级,方法优先级越高,越先接受到事件。默认优先级0。
1.1、threadMode
默认threadMode值为POSTING,在事件发送线程执行订阅方法。在EventBus事件分发postToSubscription(subscription, event, isMainThread)方法中会根据注解方法的threadMode选择合适的方式执行订阅方法。
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 {
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;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
1.2、sticky
订阅方法是否订阅粘性事件,默认不订阅粘性事件。在注册订阅对象的时候,subscribe(subscriber, subscriberMethod)方法中会根据注解中设置的sticky属性决定是否向新订阅对象的订阅方法分发已有粘性事件。
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
...
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
for (Map.Entry<Class<?>, Object> entry : entries) {
Class<?> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
如果注册的订阅方法订阅粘性事件,那么会将现有符合条件的粘性事件通过checkPostStickyEventToSubscription(newSubscription, stickyEvent)方法传递给新订阅的方法执行。
private void checkPostStickyEventToSubscription(Subscription newSubscription, Object stickyEvent) {
if (stickyEvent != null) {
// If the subscriber is trying to abort the event, it will fail (event is not tracked in posting state)
// --> Strange corner case, which we don't take care of here.
postToSubscription(newSubscription, stickyEvent, isMainThread());
}
}
1.3、priority
订阅方法的优先级,而不是事件的优先级。优先级越高,订阅方法就先执行。通过subscribe(subscriber, subscriberMethod)方法注册订阅对象的时候,就会根据订阅方法中设置的priority值大小,按优先级从大到小的顺序插入到现有的订阅方法集合中。
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class<?> eventType = subscriberMethod.eventType;
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
...
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
...
}
2、解析Subscribe
在EventBus源码分析(一):构造及订阅一文的第2.1节,已经看过解析Subscribe注解的流程,借助SubscriberMethodFinder完成:
