EventBus3.0源码学习(1) register和unregister

引子

EventBus提供了一套完善的总线机制,能有效地用于模块间解耦。要使用EventBus,在项目模块的build.gradle中添加如下依赖即可:

dependencies {
    compile 'org.greenrobot:eventbus:3.0.0'
}

类定义

 1 public class EventBus {
 2 
 3     static volatile EventBus defaultInstance;
 4 
 5     private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
 6     private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
 7 
 8     private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
 9     private final Map<Object, List<Class<?>>> typesBySubscriber;
10     private final Map<Class<?>, Object> stickyEvents;
11 
12     private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() {
13         @Override
14         protected PostingThreadState initialValue() {
15             return new PostingThreadState();
16         }
17     };
18 
19     private final HandlerPoster mainThreadPoster;
20     private final BackgroundPoster backgroundPoster;
21     private final AsyncPoster asyncPoster;
22     private final SubscriberMethodFinder subscriberMethodFinder;
23     private final ExecutorService executorService;
24 
25     private final boolean throwSubscriberException;
26     private final boolean logSubscriberExceptions;
27     private final boolean logNoSubscriberMessages;
28     private final boolean sendSubscriberExceptionEvent;
29     private final boolean sendNoSubscriberEvent;
30     private final boolean eventInheritance;
31 
32     private final int indexCount;
33 
34     public static EventBus getDefault() {
35         if (defaultInstance == null) {
36             synchronized (EventBus.class) {
37                 if (defaultInstance == null) {
38                     defaultInstance = new EventBus();
39                 }
40             }
41         }
42         return defaultInstance;
43     }
44 
45     public EventBus() {
46         this(DEFAULT_BUILDER);
47     }
48 
49     EventBus(EventBusBuilder builder) {
50         subscriptionsByEventType = new HashMap<>();
51         typesBySubscriber = new HashMap<>();
52         stickyEvents = new ConcurrentHashMap<>();
53         mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
54         backgroundPoster = new BackgroundPoster(this);
55         asyncPoster = new AsyncPoster(this);
56         indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
57         subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes,
58                 builder.strictMethodVerification, builder.ignoreGeneratedIndex);
59         logSubscriberExceptions = builder.logSubscriberExceptions;
60         logNoSubscriberMessages = builder.logNoSubscriberMessages;
61         sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
62         sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
63         throwSubscriberException = builder.throwSubscriberException;
64         eventInheritance = builder.eventInheritance;
65         executorService = builder.executorService;
66     }
67 }

注册(register)

当一个对象想要从EventBus接收事件时,只需在EventBus中进行注册自己,调用EventBus.getDefault().register(this)即可。register的实现如下:

 1 public void register(Object subscriber) {
 2     Class<?> subscriberClass = subscriber.getClass();
 3     List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
 4     synchronized (this) {
 5         for (SubscriberMethod subscriberMethod : subscriberMethods) {
 6             subscribe(subscriber, subscriberMethod);
 7         }
 8     }
 9 }

第3行,查找subscriber对应的类中所有接收EventBus事件的函数,然后依次调用subscribe函数注册这些所有查到的函数。subscribe的代码如下:

 1 private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
 2     Class<?> eventType = subscriberMethod.eventType;
 3     Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
 4     CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
 5     if (subscriptions == null) {
 6         subscriptions = new CopyOnWriteArrayList<>();
 7         subscriptionsByEventType.put(eventType, subscriptions);
 8     } else {
 9         if (subscriptions.contains(newSubscription)) {
10             throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
11                     + eventType);
12         }
13     }
14 
15     int size = subscriptions.size();
16     for (int i = 0; i <= size; i++) {
17         if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
18             subscriptions.add(i, newSubscription);
19             break;
20         }
21     }
22 
23     List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
24     if (subscribedEvents == null) {
25         subscribedEvents = new ArrayList<>();
26         typesBySubscriber.put(subscriber, subscribedEvents);
27     }
28     subscribedEvents.add(eventType);
29 
30     if (subscriberMethod.sticky) {
31         if (eventInheritance) {
32             // Existing sticky events of all subclasses of eventType have to be considered.
33             // Note: Iterating over all events may be inefficient with lots of sticky events,
34             // thus data structure should be changed to allow a more efficient lookup
35             // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>).
36             Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet();
37             for (Map.Entry<Class<?>, Object> entry : entries) {
38                 Class<?> candidateEventType = entry.getKey();
39                 if (eventType.isAssignableFrom(candidateEventType)) {
40                     Object stickyEvent = entry.getValue();
41                     checkPostStickyEventToSubscription(newSubscription, stickyEvent);
42                 }
43             }
44         } else {
45             Object stickyEvent = stickyEvents.get(eventType);
46             checkPostStickyEventToSubscription(newSubscription, stickyEvent);
47         }
48     }
49 }

第3行,subscriber和subscriberMethod被封装成一个Subscription对象,Subscription描述了subscriber通过subscriberMethod对EventBus的一个事件订阅。

第4-21行,subscriptionsByEventType存储了<eventType, subscriptions>的映射关系,当分发事件时,使用该Map可以快速找到订阅了该事件的所有对象及其用于处理该事件的方法。subscriptions中的subscription,可能来自不同类的对象、同一类的不同对象、甚至同一个对象的不同方法,subscriptions以subscriberMethod.priority维护它们的降序顺序。对同一个对象的重复注册会导致第10行抛出EventBusException异常。

第23-28行,typesBySubscriber存储了<subscriber, subscribedEvents>的映射关系,当取消注册时,使用该Map可以快速找到该对象订阅的所有事件,或 判断该对象是否已经注册过了

第30-48行,stickyEvents存储了<eventType, stickyEvent>的映射关系,与普通事件不同,除非显示移除,否则EventBus中总是保留该类事件的最近一次事件实例。当subscriberMethod.sticky为true,从stickyEvents中查找eventType对应的stickyEvent发送给该对象。若eventInheritance为true,查找stickyEvents中所有eventType及其子类的事件进行发送。

取消注册(unregister)

当一个类不再需要接收EventBus时,它需要在EventBus中取消注册,即调用EventBus.getDefault().unregister(this)。这很重要,在实际开发中,很多内存泄漏问题都是由于注册之后没有取消注册导致的。unregister的实现如下:

 1 public synchronized void unregister(Object subscriber) {
 2     List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
 3     if (subscribedTypes != null) {
 4         for (Class<?> eventType : subscribedTypes) {
 5             unsubscribeByEventType(subscriber, eventType);
 6         }
 7         typesBySubscriber.remove(subscriber);
 8     } else {
 9         Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
10     }
11 }

使用typesBySubscriber查找subscriber订阅了的所有事件类型,依次调用unsubcribeByEventType函数取消subscriber对每个eventType的订阅,然后将subscriber从typesBySubscriber中移除。unsubcribeByEventType的实现如下:

 1 private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
 2     List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
 3     if (subscriptions != null) {
 4         int size = subscriptions.size();
 5         for (int i = 0; i < size; i++) {
 6             Subscription subscription = subscriptions.get(i);
 7             if (subscription.subscriber == subscriber) {
 8                 subscription.active = false;
 9                 subscriptions.remove(i);
10                 i--;
11                 size--;
12             }
13         }
14     }
15 }

使用subscriptionsByEventType查找eventType对应的subscriptions,然后移除subscriptions中所有subscription.subscriber==subscriber的subscription,并将subscription.active置为false。

总结

EventBus中与事件分发相关的底层实现主要涉及三个Map:

  • subscriptionsByEventType--<eventType, subscriptions>,主要用于事件分发,用于快速找到event的订阅者集合;
  • typesBySubscriber--<subscriber, eventType>,主要用于取消注册,用于快速查找对象订阅的事件类集合;
  • stickyEvents保存了stickyEvent的最近一次事件实例。
posted on 2017-10-17 18:04  游不动の鱼  阅读(1395)  评论(0编辑  收藏  举报