EventBus for fast Android Development Series Communication

Source: Internet
Author: User

Let's talk about the MarkDown editor of the blog Park. When it was launched, I was very happy that the blog Park supported MarkDown. It was useless if I tried it and found that the support was not complete, this article was written in another editor. It was copied and found .. It's too bad. As a technical blog community, we should improve the Code support. If the 'intra-row blocks' does not support code block, there cannot be any blank lines in the code segment, and the Code cannot be identified when there is no blank line. In addition, I tried to use MarkDown to send a draft, and the sidebar on the right was squeezed below the screen, which also affected the blog layout .. No more .. You can simply edit the title and code and directly publish it.

Overview and Basic Concepts

** EventBus ** is an Android-optimized publish/subscribe message bus that simplifies communication between components in the application and between components and background threads. For example, if you request a network and notify the UI through Handler or Broadcast when the network returns, the two Fragment must communicate with each other through Listener. These requirements can be implemented through ** EventBus.

As a message bus, there are three main elements:

  • Event: Event
  • Subscriber: Event Subscriber that receives specific events.
  • Publisher: Event Publisher, used to notify Subscriber of an event
Event

** Event ** can be any type of object.

Subscriber

In EventBus, conventions are used to specify event subscribers for simplified use. That is, all event subscriptions start with onEvent. Specifically, the function names are onEvent, onEventMainThread, onEventBackgroundThread, and onEventAsync. This is related to ThreadMode.

Publisher

You can send events anywhere in any thread and directly call the 'post (Object) 'method of EventBus. You can instantiate the EventBus Object by yourself, but generally you can use the default singleton: 'eventbus. getDefault () '. The function that subscribes to corresponding types of events is automatically called based on the type of the post function parameter.

ThreadMode

As mentioned above, the Subscriber function name can only be those four, because each event subscription function is associated with a 'threadmode' and ThreadMode specifies the function to be called. There are four threadmodes:

  • PostThread: the event is handled in the same process as the event is sent, so the event processing time should not be too long. Otherwise, the event sending thread will be affected, and this thread may be the UI thread. The corresponding function name is onEvent.
  • MainThread: event processing is executed in the UI thread. The event processing time cannot be too long. Needless to say, it will be ANR long and the corresponding function name is onEventMainThread.
  • BackgroundThread: event processing is performed in a background thread. The corresponding function name is onEventBackgroundThread. Although the name is BackgroundThread, event processing is performed in the background thread, however, the event processing time should not be too long, because if the thread sending the event is a background thread, the event will be executed directly. If the current thread is a UI thread, the event will be added to a queue, A thread processes these events in sequence. If the processing time of an event is too long, it will block the dispatching or processing of subsequent events.
  • Async: event processing is executed in a separate thread, mainly used to execute time-consuming operations in the background thread. Each event starts a thread (with a thread pool ), but it is best to limit the number of threads.

Different threadmodes are used according to the function names of event subscriptions. If you want to display data in the UI thread when loading data in the background thread, the subscriber only needs to name the function onEventMainThread.

Easy to use

The basic steps are as follows. Click this link to view the example and introduction.

Implementation

** EventBus ** is easy to use, but if you do not know how to use it, you will never know how to use it, so we need to study its implementation and Read the fucking Code. In fact, it is mainly a 'eventbus' class. When you look at the Code, you need to understand several concepts and members. After understanding these concepts, you can understand the implementation well.

  • EventType: the parameter in the onEvent \ * function, indicating the Event Type
  • Subscriber: subscription source, that is, the object registered by register, which contains the onEvent \ * Function
  • SubscribMethod: a specific onEvent \ * Method in 'subscriber '. The internal Member contains a method Member of the 'method' type to indicate this onEvent \ * Method, A 'threadmode' member ThreadMode indicates the event processing thread and A 'Class <?> 'Eventtype member of 'type' indicates the event type 'eventtype '.
  • Subscriber, indicating a Subscription object, including the Subscription source 'subscriber ', a specific method in the Subscription source 'subscribmethod', the priority of this Subscription 'priopity'


After learning about the above concepts, You can see several important members in 'eventbus '.

  Map<Class<?>, CopyOnWriteArrayList<Subscription>>  Map<Object, List<Class<?>>>  Map<Class<?>, Object>   Map<Class<?>, List<Class<?>>> eventTypesCache =  HashMap<Class<?>, List<Class<?>>>();

Use 'eventbus. getDefault (). the register 'method can be used to register with 'eventbus' to subscribe to events. 'register 'has many reload forms, but most of them are marked as 'deprecated', so it is better not to subscribe to events, as mentioned above, all event handling methods start with * onEvent * and can be modified using the register method. However, the corresponding method is discarded and should not be used, use the default * onEvent *. In addition to the discarded register method, there are also four 'register 'Methods ** public **.

 , 0  register(Object subscriber,  , 0  registerSticky(Object subscriber, 

We can see that the four methods call the same method:

   register(Object subscriber, String methodName,  sticky, <SubscriberMethod> subscriberMethods =

 

The first parameter is the subscription source, and the second parameter uses the specified method name convention. The default parameter starts with * onEvent *, which means that the default parameter can be modified, but as mentioned above, the method has been abandoned and it is best not to use it. The third parameter indicates whether it is * Sticky Event *, and the second parameter indicates the priority.

In the above method, a class named 'subscribermethodfinder 'is used to locate a 'subscribermethod' list through its 'findsubscribermethods' method, as we have known before, 'subscribermethod' indicates an onEvent \ * method in the Subcriber. We can see that the role of the 'subscribermethodfinder 'class is to find all the methods in the Subscriber (that is, the default onEvent) method. Each method found is represented as a 'subscribermethod' object.

'Subscribermethodfinder 'will not be analyzed, but there are two points to know:

After all the event handling methods in * Subscriber * are found, the 'subscribe' method is called for registration for each found method (represented as the 'subscribermethod' object. The 'subscribe' method does three things:

Through the subing between * Subscriber * and * EventType *, we can easily cancel the event receiving by a Subscriber and use * EventType * to map * Sucscribtion, you can easily send events to every subscriber.

Post event

You can directly call 'eventbus. getDefault (). post (Event) to send events. The events can be sent to the corresponding Event subscriber Based on the Event type.

 =<Object> eventQueue == Looper.getMainLooper() ===   EventBusException("Internal error. Abort state was not reset" (!0= = 

We can see that the post object uses 'postingthreadstate' and is 'threadlocal'. Let's take a look at the definition of 'postingthreadstate:

  <Object> eventQueue =  ArrayList<Object>

  postSingleEvent(Object event, PostingThreadState postingState) <?  Object> eventClass =<Class<?>> eventTypes = findEventTypes(eventClass);      subscriptionFound =  countTypes = ( h = 0; h < countTypes; h++) {         Class<?> clazz =<Subscription> (= (subscriptions !=  && !subscriptions.isEmpty()) {             == aborted =                     aborted == = = =  (!"No subscribers registered for event " + (eventClass != NoSubscriberEvent. && eventClass != SubscriberExceptionEvent. NoSubscriberEvent(

Next, go to step 2, traverse the List obtained in step 1, and perform step 3 operations on each class Object (that is, the event type) in the List, all subscribers of this event type are found to send events to them. As you can see, ** when we Post an event, the parent event of this event (the parent event of the event class) will also be Post, therefore, if an event subscriber receives an Object-type event, it can receive all events **.

We can also see that the event is actually sent through 'posttosubstatus' in Step 4, and the event and subscriber are saved to 'postingstate' before sending. Let's take a look at 'posttosubnotification'

  postToSubscription(Subscription subscription, Object event,   IllegalStateException("Unknown thread mode: " +

  • If it is PostThread, directly execute
  • If it is MainThread, judge the current thread. If it is already the UI thread, it will be executed directly; otherwise, it will be added to the 'mainthreadposter' queue.
  • If it is a background thread, if it is currently a UI thread, add it to the 'backgroundposter' queue; otherwise, directly execute
  • For Async, add the 'asyncposter' queue.
BackgroundPoster
  = ( (!= 

HandlerPoster

'Mainthreadposter' is a 'handlerposter' object. 'handlerposter' inherits from 'handler'. The constructor receives a 'login' object. When an event is sent to 'handlerposter' enqueue, this event will be added to the queue like 'backgroundposter', but if the Message is not sent, the Message will be sent to itself.

= ( (!=  (!  EventBusException("Could not send handler message"

AsyncPoster

'Asyncposter' is simple, and every event is added to the thread pool for processing.

 =

You can use 'registersticky' to register the Stick event handler. As we know before, either 'register 'or 'registersticky' will call the 'subscribe' function, there is such a piece of code in 'subscribe:

 

That is, the event type is used to check whether the corresponding event exists from 'stickyevents'. If yes, the event is directly sent to the subscriber. When is this event stored? Like 'register 'and 'registersticky', there is also a 'poststicky' function with 'post:

= (stickyEvent !=         postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() ==

Event Priority

The 'register 'function overload has a subscriber priority that can be specified. We know that 'eventbus' has an event type mapped to List <subcategory>. In this ing, all subpartitions are sorted by priority. In this way, when a post event is initiated, a higher priority will first receive an opportunity to process the event.

An application with a higher priority can finally pass events through the 'canonicaleventdelivery' method. However, note that 'the ThreadMode of this event must be postthread ', and only events that are being processed.

# Disadvantages
There is no way to communicate between processes. If there are multiple processes in an application, there is no way to communicate.

# Notes and highlights

  • The same onEvent function is not registered twice, so it cannot be registered in a class and also in the parent class. ** do not register in the parent class, only register in the subclass, because a parent class is automatically registered when a class is registered **.
  • When an event is Post, the event of the parent class of this event class will also be Post.
  • When the Post event is not processed by the Subscriber, the 'nosubscriberevent' event is Post. When the Subscriber fails to be called, The 'subscriberexceptionevent' event is Post.
Others

There is also an Util package in 'eventbus'. The main function is to execute a Runnable through 'asyncexecutor' and use the internal RunnableEx (abnormal Runnable can be searched) when Runnable throws an exception, send a message through 'eventbus' to display the error dialog box. Not very interested, not for analysis

Project home: https://github.com/greenrobot/EventBus

 

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.