Previously overview
In the previous article, we introduced the basic use of eventbus and some advanced techniques. This and several subsequent blogs will focus on parsing Eventbus.java to see how the author gracefully implements this seemingly simple event distribution/reception mechanism.
This article outlines
Profiling the register process, let's get started!
Method signature
The complete register method is signed as follows, and we usually call the register (this ) in fact the final call to the register (this, false, 0), in addition, using the Registersticky (This) makes the call, in fact, in the end is going to the same method.
Private synchronized void Boolean int Priority ) { List<SubscriberMethod> subscribermethods = Subscribermethodfinder.findsubscribermethods ( Subscriber.getclass ()); for (Subscribermethod subscribermethod:subscribermethods) { Subscribe (subscriber, Subscribermethod, sticky, priority);} }
- Declared as synchronized, because the subscribe method that is called is required to be executed in the synchronization block;
- This register method actually does only one thing: Take out all the onevent methods of the target class (through reflection), subscribe to events (via subscribe)
Subscribe translation came to be "subscription, ordering", is the focus of the analysis of the content, the following to uncover her mysterious veil:
subscribe/Subscription
For people who are familiar with design patterns, the first to see Eventbus, the mind must be the Observer pattern/observer, this mode of implementation is nothing more than--the event's distributor has a list of subscribers, each time an event occurs, The distributor traverses and notifies subscribers in the list. Subscribers are free to join/exit their subscription list.
Register is a process of subscribing, so what you do in subscribe is "Add target method of target class to Subscriber list ". Let's combine the code to see.
Private voidSubscribe (Object subscriber, Subscribermethod Subscribermethod,BooleanStickyintPriority ) {Class<?> EventType =Subscribermethod.eventtype; Copyonwritearraylist<Subscription> subscriptions =Subscriptionsbyeventtype.get (EventType); Subscription newsubscription=NewSubscription (subscriber, Subscribermethod, priority); if(Subscriptions = =NULL) {Subscriptions=NewCopyonwritearraylist<subscription>(); Subscriptionsbyeventtype.put (EventType, subscriptions); } Else { if(Subscriptions.contains (newsubscription)) {Throw NewEventbusexception ("subscriber" + subscriber.getclass () + "already registered to event" +EventType); } } //Starting with Eventbus 2.2 We enforced methods to is public (might change with annotations again)//subscriberMethod.method.setAccessible (true); intSize =subscriptions.size (); for(inti = 0; I <= size; i++) { if(i = = Size | | newsubscription.priority >Subscriptions.get (i). Priority) {Subscriptions.add (i, newsubscription); Break; }} List<Class<?>> subscribedevents =Typesbysubscriber.get (subscriber); if(Subscribedevents = =NULL) {subscribedevents=NewArraylist<class<?>>(); Typesbysubscriber.put (subscriber, subscribedevents); } subscribedevents.add (EventType); if(sticky) {if(eventinheritance) {//Existing Sticky events of all subclasses of EventType has to be considered. //note:iterating over all events 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); } }}
Event is the key to the decoupling of the distributor/Subscriber, which communicates through the class of event. Therefore, we first take out the subscription list (Subscriptionsbyeventtype) of the target event, add the new rules, and throw exception if the register is duplicated. In the process of joining, the position that is inserted into the list is determined by the priority (the larger the int value, the higher the position, the greater the precedence). The next step is to add the correspondence between the Subscriber (that is, the target class) and the new EventType to Typesbysubscriber , which is used in subsequent lookups.
In the case of sticky , if the Eventbus supports event inheritance (eventinheritance = = True), all events for EventType and its ancestor classes are redistributed again, If not supported, only the target eventtype is distributed. (The event distributed at this time is from stickyevents)
unregister/logoff
This article finally analyzes the logoff process, the code is very simple.
Public synchronized void Unregister (Object subscriber) { List<Class<?>> subscribedtypes = typesbysubscriber.get (subscriber); if NULL ) { for ( class<?> eventtype:subscribedtypes) { Unubscribebyeventtype ( Subscriber, EventType); } Typesbysubscriber.remove (subscriber); Else { "subscriber to unregister is not registered before:" + Subscriber.getclass ());} }
Unregister, the binding relationship of the Eventtype-subscriber is first lifted (processed subscriptionsbyeventtype), and finally Subscriber-eventtypes unbind.
Next stage Notice
Anatomy of the Post process
[Eventbus Source parsing] Eventbus.register Method Details