Eventbus 2.4 Source Code Analysis

Source: Internet
Author: User
Tags eventbus

Eventbus Introduction

This article was written based on Eventbus 2.4.

Android optimized event bus that simplifies communication between activities, fragments, Threads, Services, etc. Less code, better quality.

The above is the code from the official repo, roughly speaking, simplifying the communication between components, reducing code, and improving quality.

In fact, and eventbus the earliest is in the Qzone code, the space inside there is a call eventcenter things, has been optimized some, at that time to see the source of the realization of the original is based on the Eventbus to change a realization. Probably is the implementation of the annotation to the interface implementation, in addition to the event type to find the subscriber's pattern, completely through the type of event of the constant to judge, register when the direct designation of what type of interest, The auxiliary judgment is referred to by the event sender. This realization is a matter of opinion, although directly through the interface is certainly capable of lifting high performance. Here to spit Groove is the implementation of the changes, directly to a lot of external interface name to get rid of, why?

The benefits of Eventbus are obvious, completely decoupling the relationship between the request chain, to avoid the requestor is long held, and more than the broadcast lighter, more powerful than Localbroadcast, the interface is simple and practical. Shortcomings, such as the definition of various events is a workload.

SOURCE Analysis-Registration (register)

EventBus.java:

privatesynchronizedvoidregisterbooleanint priority) {    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());    for (SubscriberMethod subscriberMethod : subscriberMethods) {        subscribe(subscriber, subscriberMethod, sticky, priority);    }}

Register, roughly is to go to subscriber inside first find those OnEvent method (the current implementation is still based on onevent this prefix), look for the time will be to judge the suffix, divided into the post thread, the main thread, background thread, As well as asynchronous threads, the official repo mentioned here after 3.0 may be replaced by annotation implementations.

The sticky parameter is the sticky event concept, poststicky and Registersticky correspond, and Stickyevent records the last EventType event of the poststicky, so that when Registersticky , it immediately checks for previous post events, thus avoiding certain events to implement their own caches. The scenario is that some activity/fragment are interested in events that occur before they are created, which avoids the need to implement caching (and of course, the fact that the scenario is still relatively small, because most of the things we still have to record)

SubscriberMethod.java:

final class SubscriberMethod {    final Method method;    final ThreadMode threadMode;    final Class<?> eventType;    /** Used for efficient comparison */    String methodString;}

Subscribermethod the method reference, the threading pattern (obtained in findsubscribermethods), EventType, and methodstring to improve method.equals performance.

Then look at the implementation of the Subscribe method, and at the end of the register, all the methods found are executed once subscribe
EventBus.java:

//must be called in synchronized blockPrivate void Subscribe(Object subscriber, Subscribermethod Subscribermethod,BooleanStickyintPriority) {class<?> EventType = Subscribermethod.eventtype;//Copyonwritearraylist is a immutablearraylist, Add/set method will return a new ArrayList    //Subscriptionsbyeventtype is a Hashmap,key is the event type, value is the subscriber arraycopyonwritearraylist<subscription> subscriptions = Subscriptionsbyeventtype.get (EventType); Subscription newsubscription =NewSubscription (subscriber, Subscribermethod, priority);//The EventType does not exist in the map, create a new subscription array and put it in the map    if(Subscriptions = =NULL) {subscriptions =NewCopyonwritearraylist<subscription> ();    Subscriptionsbyeventtype.put (EventType, subscriptions); }Else{//Repeat registration when throwing an exception, if the application if it feels harmless can actually return directly        if(Subscriptions.contains (newsubscription)) {Throw NewEventbusexception ("subscriber"+ subscriber.getclass () +"already registered to event"+ EventType); }    }//According to the priority to add to the corresponding location, high priority in front will be processed first    intSize = Subscriptions.size (); for(inti =0; I <= size; i++) {if(i = = Size | | newsubscription.priority > Subscriptions.get (i). Priority) {Subscriptions.add (i, newsubscription); Break; }    }//Typesbysubscriber is another map, as its name implies, a map with subscriber as the key and is used in    ///1) isregistered (Object Subscriber) method to determine if it is registered, use space to change time    ///2) unregister can get all the EventType of Subscriber subscription and then remove from map to avoid the need to traverse all EventType maplist<class<?>> subscribedevents = typesbysubscriber.get (subscriber);if(Subscribedevents = =NULL) {subscribedevents =NewArraylist<class<?>> ();    Typesbysubscriber.put (subscriber, subscribedevents); } subscribedevents.add (EventType);//Sticky event, go and find out if there are any previous post events, then post to the subscriber immediately .    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 is 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<?&gt, 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); }    }}
SOURCE Analysis-Send event (POST)

Take a look at the corresponding post logic

EventBus.java:

/** Posts The given event to the event bus. * / Public void Post(Object event) {//Get the status of the current post thread, the implementation is pasted below, Currentpostingthreadstate is the threadlocal<postingthreadstate> variable, Each thread get and set is a separate copy of the dataPostingthreadstate postingstate = Currentpostingthreadstate.get ();//Add the event to the events queuelist<object> eventqueue = Postingstate.eventqueue; Eventqueue.add (event);//If the posting event is not currently    if(!postingstate.isposting) {//Set whether the main threadPostingstate.ismainthread = looper.getmainlooper () = = Looper.mylooper ();//Set current post eventPostingstate.isposting =true;//Canceled status, throwing exceptions        if(postingstate.canceled) {Throw NewEventbusexception ("Internal error. Abort state is not reset "); }Try{//Cyclic post from EventQueue inside the event             while(!eventqueue.isempty ()) {Postsingleevent (Eventqueue.remove (0), postingstate); }        }finally{//Position backPostingstate.isposting =false; Postingstate.ismainthread =false; }    }}Final StaticClass Postingthreadstate {FinalList<object> EventQueue =NewArraylist<object> ();Booleanisposting;BooleanIsmainthread;    Subscription Subscription; Object event;//Can be canceleventdelivery to cancel event delivery    BooleanCanceled;}//Post processing for individual eventsPrivate void postsingleevent(Object event, Postingthreadstate postingstate)throwsError {class<?> EventClass = Event.getclass ();BooleanSubscriptionfound =false;//Inheritance chain processing, such as the subscriber of the parent class of the event itself, is also received, and the default is true when Getdefault.     if(eventinheritance) {list<class<?>> eventtypes = lookupalleventtypes (EventClass);intCounttypes = Eventtypes.size (); for(inth =0; H < counttypes;            h++) {class<?> clazz = Eventtypes.get (h);        Subscriptionfound |= Postsingleeventforeventtype (event, Postingstate, Clazz); }    }Else{subscriptionfound = Postsingleeventforeventtype (event, Postingstate, EventClass); }//Not found, too weird.    if(!subscriptionfound) {if(lognosubscribermessages) {LOG.D (TAG,"No subscribers registered for event"+ EventClass); }if(sendnosubscriberevent && EventClass! = Nosubscriberevent.class && EventClass! = Subscriber Exceptionevent.class) {//did not expect to have this logic, did not find subscribers, will send a nosubscriberevent outPostNewNosubscriberevent ( This, event)); }    }}//To post a single event for a specific eventPrivate Boolean Postsingleeventforeventtype(Object event, Postingthreadstate postingstate, class<?> EventClass) {copyonwritearraylist<subscription> subscriptions;//Find all subscriptions to this event    synchronized( This) {subscriptions = Subscriptionsbyeventtype.get (EventClass); }if(Subscriptions! =NULL&&!subscriptions.isempty ()) {//Traverse all subscriptions         for(Subscription subscription:subscriptions)            {postingstate.event = event; Postingstate.subscription = subscription;Booleanaborted =false;Try{//Results The actual post is also implemented within this methodPosttosubscription (subscription, event, Postingstate.ismainthread);            aborted = postingstate.canceled; }finally{postingstate.event =NULL; Postingstate.subscription =NULL; postingstate.canceled =false; }//If Cancel is stopped, the event will not continue to pass            if(aborted) { Break; }        }return true; }return false;}//specific event distributionPrivate void posttosubscription(Subscription Subscription, Object event,BooleanIsmainthread) {//Here is a very powerful feature of Eventbus, based on the subscriber's subscription method to listen to the thread to handle    //If the post and the listener method are immediately invoke the corresponding method on the same thread    //Otherwise it will go into the queue to the corresponding thread handler for processing    Switch(Subscription.subscriberMethod.threadMode) { CasePostthread:invokesubscriber (subscription, event); Break; CaseMainthread:if(Ismainthread)            {Invokesubscriber (subscription, event); }Else{mainthreadposter.enqueue (subscription, event); } Break; CaseBackgroundthread:if(Ismainthread)            {backgroundposter.enqueue (subscription, event); }Else{Invokesubscriber (subscription, event); } Break; CaseAsync:asyncPoster.enqueue (subscription, event); Break;default:Throw NewIllegalStateException ("Unknown thread mode:"+ Subscription.subscriberMethod.threadMode); }}
End

Generally speaking about the register and post this pair of more commonly used interfaces, and some other implementations like Eventbusbuilder,subscriberexception,canceleventdelivery, Asyncexecutor is not here to repeat, then may be a separate article on the asyncexecutor to talk about, in addition to the implementation of Otto to do a bit of analysis.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Eventbus 2.4 Source Code Analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.