Otto source code analysis, otto source code

Source: Internet
Author: User
Tags wrappers

Otto source code analysis, otto source code
Otto, an open-source project, is an event bus message framework used for communication between various modules of the program.
Reduces coupling between modules.

This project is an open-source project of payment company square hosted on github.
Https://github.com/square/otto


The basic model is that Android components can register listeners, send messages, and receive messages. The mode is the observer mode, but different from
The observer Mode Implemented by java is more decoupled and can be monitored through annotations.

The class of the master control center in otto is Bus, which registers and distributes complex events.

First, register the component that listens to the event or the component that sends the event.
Call the register Method of Bus
Publicvoidregister (Object object)

The explanation for this method is as follows:

/**   * Registers all handler methods on {@code object} to receive events and producer methods to provide events.   * If any subscribers are registering for types which already have a producer they will be called immediately   * with the result of calling that producer.   * If any producers are registering for types which already have subscribers, each subscriber will be called with   * the value from the result of calling the producer.   *   * @param object object whose handler methods should be registered.   * @throws NullPointerException if the object is null.   */

All the event processing methods (subscription methods) of this object are used to process received events, and the producer method is used to provide events.
This registrant can receive or produce events.
Then I talked about some special situations during registration,
(1) If an event type is subscribed to during registration and there are methods for generating the event, the method for generating the event will be immediately called,
Distribute events to this subscriber method.
(2) If a subscriber already exists in the method that generates a specific event at registration, the subscriber will call the event generation method to distribute the event to the event.
Subscriber.
Implementation Analysis of the method:

Public void register (Object object) {if (object = null) {throw new NullPointerException ("Object to register must not be null. ");} // check whether the domain name has been registered in the main thread. By default, enforcer must be called in the main thread. enforce (this); // key is the class Object Map of the event <Class <?>, EventProducer> foundProducers = handlerFinder. findAllProducers (object );

The above code is used to obtain all the producer methods of the registered object, which can correspond to the producer methods of multiple events.
Only one producer method can be registered for one registered object.
 
HandlerFinder is an instance of HandlerFinder and an auxiliary class of Bus. It is used to locate all the producers and subscribers of the specified registrant.
HandlerFinder. findAllProducers (object) returns a map set. The key is an instance of the event Class, and the value
EventProducer is the packaging of the producer method and the registered instance.

It can be seen from this that although the code of this method is not continued, we can guess that the registrant can only have one producer for the same event.
We continue to track the code of the HandlerFinder findAllProducers () method.
HandlerFinder is just an excuse, and then implements an internal class in it
As follows:

HandlerFinder ANNOTATED = new HandlerFinder() {    @Override    public Map<Class<?>, EventProducer> findAllProducers(Object listener) {      return AnnotatedHandlerFinder.findAllProducers(listener);    }    @Override    public Map<Class<?>, Set<EventHandler>> findAllSubscribers(Object listener) {      return AnnotatedHandlerFinder.findAllSubscribers(listener);    }  };

This code will be called:
AnnotatedHandlerFinder. findAllProducers (listener)

Go in and check the code.

Static Map <Class <?>, EventProducer> findAllProducers (Object listener) {final Class <?> ListenerClass = listener. getClass (); Map <Class <?>, EventProducer> handlersInMethod = new HashMap <Class <?>, EventProducer> (); // check whether the listenerClass producer method does not exist. You need to find the method and put it in PRODUCERS_CACHE. // PRODUCERS_CACHE is a map, which can be a class Object of listener, the value is the if (! PRODUCERS_CACHE.containsKey (listenerClass) {loadAnnotatedMethods (listenerClass);} // The following Code encapsulates all the producer methods and returns them to the caller's Map <Class <?>, Method> methods = PRODUCERS_CACHE.get (listenerClass); if (! Methods. isEmpty () {for (Map. Entry <Class <?>, Method> e: methods. entrySet () {EventProducer producer = new EventProducer (listener, e. getValue (); handlersInMethod. put (e. getKey (), producer) ;}return handlersInMethod ;}

Let's go back to the Bus register method.

// Key is the class Object Map of the event <Class <?>, EventProducer> foundProducers = handlerFinder. findAllProducers (object); for (Class <?> Type: foundProducers. keySet () {// the following code is used to check whether the event has been registered. A single event can only be registered once. final EventProducer producer = foundProducers. get (type); EventProducer previousProducer = producersByType. putIfAbsent (type, producer); // checking if the previous producer existed if (previousProducer! = Null) {throw new IllegalArgumentException ("Producer method for type" + type + "found on type" + producer.tar get. getClass () + ", but already registered by type" + previousProducer.tar get. getClass () + ". ");} // check whether the registrant registers for this event exists. If yes, call back the registrant Set <EventHandler> handlers = handlersByType. get (type); if (handlers! = Null &&! Handlers. isEmpty () {for (EventHandler handler: handlers) {dispatchProducerResultToHandler (handler, producer );}}}
This line of code is used for callback.
DispatchProducerResultToHandler (handler, producer );
The specific implementation is to call the producer event through reflection, pass the event to handler, and then pass the reflection
Callback registration method.

Continue...

// If a registrant handles this event, callback the registrant Map <Class <?>, Set <EventHandler> foundHandlersMap = handlerFinder. findAllSubscribers (object); for (Class <?> Type: foundHandlersMap. keySet () {// The type variable is the class object Set <EventHandler> handlers = handlersByType of the event. get (type); if (handlers = null) {// concurrent put if absent Set <EventHandler> handlersCreation = new CopyOnWriteArraySet <EventHandler> (); handlers = handlersByType. putIfAbsent (type, handlersCreation); if (handlers = null) {handlers = handlersCreation ;}} final Set <EventHandler> foundHandlers = foundHandlersMap. get (type); handlers. addAll (foundHandlers );}

The regeister method is completely explained.

Continue to check the post (event) method.
This method is used to distribute the event to all methods that register the event.
This event may fail to be distributed. It encapsulates a DeadEvent object and resends it. However, this DeadEvent object is not processed...

Public void post (Object event) {if (event = null) {throw new NullPointerException ("Event to post must not be null. ");} enforcer. enforce (this); // returns all class objects (parent class objects and their own) of this event that inherit the relation chain. Set <Class <?> DispatchTypes = flattenHierarchy (event. getClass (); // call boolean dispatched = false to register all classes in the event family; for (Class <?> EventType: dispatchTypes) {// obtain all the registration methods related to eventType Set <EventHandler> wrappers = getHandlersForEventType (eventType ); // Insert the packaging class of the registration method to be called back into the queue processed by the current thread. if (wrappers! = Null &&! Wrappers. isEmpty () {dispatched = true; for (EventHandler wrapper: wrappers) {enqueueEvent (event, wrapper) ;}}// if not processed, resend it once, however, no logic for re-processing is found. if (! Dispatched &&! (Event instanceof DeadEvent) {post (new DeadEvent (this, event);} dispatchQueuedEvents ();}

The following is the unregister (listener) method)
Methods for deleting production events related to this listener object and for registering listeners

Public void unregister (Object object) {if (object = null) {throw new NullPointerException ("Object to unregister must not be null. ");} enforcer. enforce (this); Map <Class <?>, EventProducer> producersInListener = handlerFinder. findAllProducers (object); for (Map. Entry <Class <?>, EventProducer> entry: producersInListener. entrySet () {final Class <?> Key = entry. getKey (); EventProducer producer = getProducerForEventType (key); EventProducer value = entry. getValue (); if (value = null |! Value. equals (producer) {throw new IllegalArgumentException ("Missing event producer for an annotated method. Is" + object. getClass () + "registered? ") ;} ProducersByType. remove (key). invalidate () ;}// return all registered methods of the current object, set it to invalid, and delete Map <Class <?>, Set <EventHandler> handlersInListener = handlerFinder. findAllSubscribers (object); for (Map. Entry <Class <?>, Set <EventHandler> entry: handlersInListener. entrySet () {// return the Set <EventHandler> currentHandlers = getHandlersForEventType (entry. getKey (); Collection <EventHandler> eventMethodsInListener = entry. getValue (); if (currentHandlers = null |! CurrentHandlers. containsAll (eventMethodsInListener) {throw new IllegalArgumentException ("Missing event handler for an annotated method. Is" + object. getClass () + "registered? ") ;}For (EventHandler handler: Listener) {if (eventMethodsInListener. contains (handler) {handler. invalidate () ;}} currentHandlers. removeAll (eventMethodsInListener );}}
To sum up,
(1) A single event can only have one method to generate this event. If there are multiple methods that will report non-check exceptions, only one source or only allowed to generate such events
There is a living source.
(2) A single event can have multiple methods for registering and listening to the same event, which will be distributed to them as long as they exist.
(3) follow the official demo to try to have only one Bus instance. First, reduce memory consumption and facilitate distribution, therefore, the method for registering and listening for distribution to other Bus will not be available.

This EventBus message framework is suitable for the message distribution work of the push processing center. It can be decoupled and distributed to various modules of the program.

Square also has many good open-source projects,
The network library okhttp supports both http and spdy and github addresses. Https://github.com/square/okhttp;
Picasso (picasso), github address for image processing Https://github.com/square/picasso;
A calendar control library, including Android and iOS. github address Https://github.com/square/android-times-square(Android version ).
Open-source projects of other square companies: Https://github.com/square





How to analyze website source code

This is easy to view web pages. for interactive web pages (such as compiled using ASP), you are familiar with programming languages. If CSS is used, you must be familiar with CSS. As for some web pages that are made in combination, it is difficult and I am not too refined.
 
C ++ source code analysis?

In this case, you must have a c ++ Foundation, so I recommend a book to you.
Hou Junjie's slt source code analysis. Needless to say, stl is a high-quality product.

This book is very good, but the requirements are also relatively high.

I don't know who said a word: What kind of books are useless, but it will be especially useful for special people and special time!

The source code is much better. You can check a lot of code after some c ++ forums, but the quality is not guaranteed!
I personally think that in order to improve the level, we need to look at some excellent products. No matter how high the starting point is, this road will eventually go !!

Only suggestions!

Related Article

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.