Why we use Event Bus
In the previously android app, we often use intent or handler to deliver the message between android’s components, that will make the code a little complex and impact the app’s performance when deliver large object.
Now there may be a better way by using Event Bus. Event Bus can decouples the senders and receivers which are usually different components, also make your code simpler.
So what are the most popular libraries about Event Bus using in android?
Guava(番石榴)
Obviously, Guava is not the fruit at here.
The Guava project contains several of Google's core libraries that we rely on in our Java-based projects: collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and
EventBus
. Each of these tools really do get used every day by Googlers, in production services.
Github:
https://github.com/google/guava
Otto
Otto is an event bus designed to decouple different parts of your application while still allowing them to communicate efficiently. Forked from Guava, Otto adds unique functionality refined event bus as well as specialising it to the Android platform.
Github:
https://github.com/square/otto
EventBus
Today I will analysing the source code of EventBus.
EventBus Introduction
EventBus is publish/subscribe event bus optimized for Android.
- simplifies the communication between components
- decouples(解耦) event senders and receivers
- performs well with Activities, Fragments, and background threads
- avoids complex and error-prone(易于出错) dependencies and life cycle issues
- makes your code simpler
- is fast
- is tiny (<50k jar)
- is proven in practice by apps with 100,000,000+ installs
-
has advanced features like delivery threads, subscriber priorities, etc.
How to use EventBus
EventBus in 3 steps
-
Define events:
public class MessageEvent { /* Additional fields if needed */ }
- Prepare subscribers:
eventBus.register(this);
public void onEvent(AnyEventType event) {/* Do something */};
- Post events:
eventBus.post(event);
ThreadMode
onEvent(EventType event)
- PostThread is default ThreadMode.
- Subscriber will be called in the same thread which is posting the event.
onEventMainThread(EventType event)
- Subscriber will be called in the main thread.
- If the posting thread is main thread, onEventMainThread(EventType) will be called directly; If not, the Event will be sent to main thread by the handler, then call the onEventMainThread(EventType) in handleMesage(Message).
- onEventMainThread(EventType) must return quickly to avoid blocking the main thread.
onEventBackgroundThread(EventType event)
- Subscriber will be called in a background thread.
- onEventBackgroundThread(EventType) will be called directly if posting thread is not main thread. If posting thread is the main thread, EventBus uses a single background thread, that will deliver all its events sequentially.
- onEventBackgroundThread(EventType) must return quickly to avoid blocking the background thread.
onEventAsync(EventType)
- Subscriber will be called in a separate thread.
- This is not relative to the posting thread or the main thread.
- Event handler methods should use this mode if their execution might take some time(network request).
EventBus EasyDemo
Subscriber:
Post:
Source Code
In most cases, we register subscriber to EventBus in onCreate method and unregister in onDestory method.
Maybe there has a question came from you what EventBus do in register.
EventBus.getDefault().register(this);
Firstly, EventBus.getDefault() is singleInstance.
Here using the double check defaultInstance is null or not to avoid concurrency(并发).
Secondly, there have serval register
methods in EventBus, but call register(Object subscriber, boolean sticky, int priority) finally.
There have 3 parameters in register method.
subscriber: usually a class which we use “this” in register(this).
sticky and priority will be analysed later.
Thirdly, in the register method will call findSubscribeMehtods(Class<?> subscriberClass)
Just analysing serval key points in this method.
line 57~59: Whether the subscriber class has been scanned before.
line 75: Get the subscriber’s methods.
line 78~82: Whether the method
start with “onEvent”, the method’s modifier is public, the method has one parameter.
line 85~93: Get the method’s thread mode by method’s suffix(后缀).
line 107: Construct a new SubscribeMethodClass() by passing the method, threadMode and eventType(parameter class Type)
line 116: Scan subscriber’s super class.
Fourthly, there has a subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) method in register
There have 4 key points in this method.
line 174~177: subscriptionsByEventType: is a type of map<string, list<subscription>>, this variable records each evenType’s subscriptions(
记录eventType的都有哪些subscription(subscriber, subscriberMethod,priority),key就是eventType
).
line 187~193: Insert the subscription in
subscriptions according to the priority.
line 195~200: typesBySubscriber: is a type of map<subscriber, list<eventType>>, this variable records each subscriber’s eventTypes(
记录subscriber都有哪些eventType, key就是
subscriber
)
line 202~212: If sticky is true and stickyEvent is not null, post the stickyEvent immediately.
EventBus.getDefault().post(title);
Firstly, add the event to the eventQueue, when the eventQueue is not empty, EventBus will call
postSingleEvent(Object event, PostingThreadState postingState)
Secondly, the eventInheritance default is true, there will call postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)
There also a key point in this methods.
line 401~403: Find the subscription by the event class type.
Thirdly, if subscription is not empty, it
will call postToSubscription(Subscription subscription, Object event, boolean isMainThread)
In this method, it will be call invokeSubscriber or enqueue the event to the poster according to isMainThread and thread mode.
At last, it will call invokeSubscriber(Subscription subscription, Object event).
In this method, we can see it invoke the event handle method by reflection.
What can we learn?
- The code use some technology to avoid concurrency, like double check in single instance, CopyOnWriteArrayList, synchronized.
- Reuse the PendingPost in pendingPostPool.
- How to use ExecutorService to schedule the thread and avoid concurrency.
- Learn Source Code also help us understand the origin of the library.
//unuse things below:
eventTypesFound:hashSet<String>: methodName>parameterTypesClassName
eventType:parameterTypesClassName
SubscriberMethod:method, threadMode, eventType
methodCache:<subscriberClass’s name, List<SubscriberMethod>>
subscriptionsByEventType:
map<string, list<subscription>>
记录eventType的都有哪些subscription(subscriber, subscriberMethod,priority),key就是eventType
typesBySubscriber:map<subscriber, list<eventType>>
分析更个类的大体作用和功能,了解某些地方的使用巧妙之处
SourceCode: