EventBus in android
When more and more functions are available for an Android app, communication between all parts of the app is usually performed in the Observer mode, that is, the registration-Notification-logout method is used to execute various controls, and the display content is often updated according to a certain status. A common solution for this scenario is to define an interface, and you need to pay attention to the control of this event to implement this interface. Interface Class: public interface OnChangedListener {void onDataChanged ();}
The observer is often implemented in the following form:
public abstract class AbsHTTPRequest { private final WeakHashMap
mListeners = new WeakHashMap
(); public interface OnChangedListener { void onDataChanged(); } /*HTTP's response*/ public abstract void onResponse(); public final void addListener(OnChangedListener listener) { mListeners.put(listener, true); } public final void removeListener(OnChangedListener listener) { mListeners.remove(listener); } protected final void notifyDataChanged() { Set
keys = mListeners.keySet(); if(keys != null) { Iterator
iterator = keys.iterator(); while(iterator.hasNext()) { iterator.next().onDataChanged(); } } }}
The implementation of a topic role (observer) is as follows:
public class LoginRequest extends AbsHTTPRequest implements OnChangedListener{public void onResponse(){addListener(this);notifyDataChanged();}@Overridepublic void onDataChanged() {// TODO Auto-generated method stubSystem.out.println("LoginRequest");}}One drawback of using the observer mode is that the coupling between components is too high, and all topic roles need to implement the same interface. The observer mode defines a one-to-many dependency, allowing multiple observer objects to listen to a topic object at the same time. If the topic role is registered with more observers, the more interfaces you need to implement and the more interface methods you need.
How to decouple the code to make the code logic clearer and more readable is a problem.
In Android, there is also an open-source library EventBus with similar functions, which can help us easily implement the observer mode and reduce the coupling between components.
About EventBus to explain the article, a lot of network industry, here we recommend an article, to explain the more detailed blog, http://www.cnblogs.com/angeldevil/p/3715934.html to EventBus understanding, it is best to start from the demo, first easy after hard. First, you need to know how to use it, and then go deep into the source code to get a step-by-step understanding of the design concept to facilitate future code debugging and module refactoring. There are many demos on the Internet. You can check them yourself. EventBus has four steps: 1. define the event type: public class MyEvent2. subscriber: EventBus. getDefault (). register (this) 3. send event: EventBus. getDefault (). post (new MyEvent () 4. the function that receives events and processes subscriber callbacks. The function name starts with onEvent.
There are several important concepts in the EventBus module. After understanding these concepts, it will be hard to understand.
Event: can be any type of object Subscriber: Subscriber, receives a specific Publisher: Publisher, used to notify Subscriber to send Parameters in the EventType: onEvent function, indicating the Event object, user-defined. Subscriber: The subscription source, that is, the object registered by register, which contains the onEvent member function.
SubscribMethod. javafinal class SubscriberMethod {final Method method;/* Method indicates this onEvent, that is, the event processing function. It also contains the subscription source */final ThreadMode threadMode; final Class
EventType;/* event object, user-Defined Object */.................................. ..}Submodules. java
Final class subscriber {final Object Subscriber;/* subscriber, that is, the Object registered by register */final SubscriberMethod subscriberMethod; /**/final int priority ;................................ ....}EventBus class has two core members.
/* EventType-> List
, Ing between events and subscription objects */private final Map
, CopyOnWriteArrayList
> SubscriptionsByEventType;/* Subscriber-> List
, The ing between the subscribed object and all its subscribed events */private final Map
> TypesBySubscriber;
Registration process:When calling the register function, the EventBus class has multiple overloaded register functions, but the author prefers to use register (this); in the register function with multiple parameters, @ deprecated is clearly marked, which is not recommended by the original author. Slave code:
public void register(Object subscriber) { register(subscriber, DEFAULT_METHOD_NAME, false, 0); }We can see that all the overloaded register functions have been called.
private synchronized void register(Object subscriber, String methodName, boolean sticky, int priority) { List
subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriber.getClass(),methodName); for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod, sticky, priority); } }
Register the register function. The default parameter DEFAULT_METHOD_NAME is the function name "onEvent". In the java radiation mechanism, all the event handler functions are named "onEvent" in a uniform manner. Only the parameters are inconsistent. OnEvent parameters are user-defined objects.
When registering, use the SubscriberMethodFinder object to call the findSubscriberMethods method and obtain the List .
The Method [] of the array object calls the getMethods () Method to obtain all the common methods of the class, which includes all its own public methods, and all the public methods inherited from the base class and implemented from the interface.
This is why our onEvent function should be defined as a public method.In the findSubscriberMethods function, such frequent traversal is performed to find the List . Each subscriber corresponds to a List , The number of onEvent functions, the returned List, and the number of items. That is, to find the event processing method in the subscription source, and find the event processing method in its parent class, return the list, and hand it
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority)
.
The relationship between Event and Subscriber is one-to-multiple. An event can be followed by multiple subscribers.
The relationship between Subscriber and Event is also one-to-many. A subscriber can subscribe to multiple events.
The subscribe method is to straighten out the above relationship and reasonably establish the map ing relationship. It mainly implements these events.
A.Store the Subscribtion object in subscriptionsByEventType according to the EventType type in SubscriberMethod. Creates a eventing between EventType and subscriber. An event can have multiple subscribers.
B.Store EventType in typesBySubscriber according to Subscriber, and create a subing between Subscriber and EventType. Each Subscriber can subscribe to multiple events.
C.If it is a Sticky subscriber, send the last saved event directly to it (if any ).
Through the subing between Subscriber and EventType, we can easily cancel receiving events for a Subscriber. Through the eventing between EventType and Sucscribtion, we can easily send corresponding events to every Subscriber of the Subscriber.
Unlike Observer, EventBus does not need to implement the interface method in Observer. In the upper-layer code, you do not need to perform the notify mechanism one by one. Through Map, the correspondence between the subscription source and the event function is decoupled, which is the core of the function.
Sending process:
EventBus. getDefault (). post (new EventType (); the parameter is a user-defined object. This is the simplest way to send events.
After an event is sent, how do all subscribers call its event method? In this case, we need to traverse the Map of subscriptionsByEventType mentioned above. Post sends an event. The entry is the post function: public void post (Object event). In the postSingleEvent function, there is an important processing function:
/** Finds all Class objects including super classes and interfaces. */ private List
> findEventTypes(Class
eventClass) { synchronized (eventTypesCache) { List
> eventTypes = eventTypesCache.get(eventClass); if (eventTypes == null) { eventTypes = new ArrayList
>(); Class
clazz = eventClass; while (clazz != null) { eventTypes.add(clazz); addInterfaces(eventTypes, clazz.getInterfaces()); clazz = clazz.getSuperclass(); } eventTypesCache.put(eventClass, eventTypes); } return eventTypes; } }
The function is to store the event class objects, Implemented interfaces, and parent class objects in a List and return them. Based on the eventTypes in the list, traverse subscriptionsByEventType to obtain the subscription source object, call event functions one by one.
Note that when you Post an event, the event's parent event (the parent event of the event class) and interface event will also be Post, therefore, if the Subscriber receives an Object-type event, that is, an onEvent (Object object) event function, the Subscriber can receive all the events.
Through this blog, EventBus establishes the correspondence between the subscription source and the event function through Map and decouples it to avoid repeated and frequent definitions of Observer interface methods.