#### **前言**
有時候,在工作的過程中用到了廣播接收器,用廣播接收器的原因是小民需要在Fragment 之間、Activity 與Fragment 之間進行通信, 需要通信就必須有對方的引用,這就導致耦合性較高, 而且廣播接收器的使用成本相對比較高,這時可以嘗試**一個新的解決方案:使用事件總線**。
我們先想象以下幾種場景:
* 你是否在開發的過程中遇到過想在Activity-B 中回調Activity-A 中的某個函數, 但Activity 又不能手動創建對象來設置一個Listener;
* 你是否想在某個Service 中想更新Activity 或者Fragment中的界面?
* 或者類的組件之間的交互問題……
以Activity 與Fragment 之間的通信為例,按照Android 官方給的思路是, Activity 實現某個接口,然后在Fragment-A 關聯上Activity 之后,將Activity 強轉為接口類型,在某個時刻Fragment 中回調這個接口,這個過程是不是有點復雜呢?如果你也這么覺得,那也就是你繼續看下去的理由了。
經過思考你會發現Android 中的Activity 、Fragment、Service 之間的交互是比較麻煩的,可能我們首先想到的是使用廣播接收器來在它們之間進行交互,例如,上述所說在Activity-B 中發送一個廣播, 在Activity-A 中注冊一個廣播接收器來接收該廣播,但**使用廣播接收器稍顯麻煩**,**如果你要將一個實體類當作數據在組件之間傳遞,那么該實體類還得實現序列化接口,這個成本實在有點高!**
代碼如下:
~~~
//ActivityA 中注冊廣播接收器
class ActivityA extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
registerReceiver(new BroadcastReceiver(){
@Override
public void onReceive (Context context , Intent intent) {
User person = intent.getParcelableExtra ("user");
}
}, new IntentFilter ("my_action"));
}
........
}
//ActivityB 中發布廣播
class ActivityB extends Activity {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent ("my_action");
intent.putExtra ("user",new User ("mr.simple"));
sendBroadcast(intent);
}
.......
}
//實體類實現序列化
class User implements Parcelable {
String name;
public User(String aName) {
name = aName;
}
.......
@Override
public void writeToParcel (Parcel dest,int flags) {
dest.writeString(name);
}
}
~~~
從上面的代碼可以看出很麻煩。
示例2:
在開發過程中,我們**經常要在子線程中做一些耗時操作,然后將結果更新到UI 線程,除了AsyncTask 之外, Thread 加Handler 是我們經常用的手段**,我們看看如下示例:
~~~
class MyActivity extends Activity {
Handler mHandler = new Handler () {
public void handleMessage (android.os.Message msg) {
if ( msg.what == 1 ) {
User user = (User)msg.obj;
// do sth
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...........
new Thread(
new Runnable() {
public void run() {
//do sth
User newUser = new User ("simple") ;
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.obj = newUser;
mHandler.send.Message(msg);
}
} ).start();
}
}
~~~
是不是又是相當麻煩!
此時,你應該冷靜下來思考一下,**還有哪些情況適合使用事件總線**,例如,穿透多個類只為一個回調的Listener...........
事件總線框架就是為了簡化這些操作而出現的,并且降低組件之間的耦合,到底如何解決呢?繼續往下看。
**事件總線就是簡化了Activity 、Fragment 、Service 等組件之間的交互,很大程度上降低了它們之間的耦合,使得我們的代碼更加簡沽,耦合性更低,提升代碼的質量。**
分析了己存在的總線庫,發現它們或多或少地存在一些問題,并且給AndroidEventBus設定了一些目標,如表所示。

打算**使用注解的形式實現事件總線**,這樣用戶在使用時比較方便,并且讓接收函數可以執行在異步線程。當然,這個庫的定制化、靈活性也是要求之一。大體思路如下:
在需要接收事件的對象初始化時將自身注冊到事件總線中,事件總線會遍歷這個對象的所屬類中的所有函數,然后根據訂閱函數的事件參數和@Subscriber 注解的tag 值構建一個EventType ,這個EventType 標識了一種事件類型,以這個EventType 為key ,訂閱對象列表為value 構建一個map,存儲這整個事件一一訂閱者表,當通過EventBus 發布事件時, 會根據事件類型和tag 來構建一個EventType ,再根據這個EventType 到表中查找所有的訂閱者,然后執行它們的訂閱函數。如圖所示。

詳情參考[AndroidEventBus](https://github.com/hehonghui/AndroidEventBus)
#### **基本結構**

AndroidEventBus類似于觀察者模式,通過register函數將需要訂閱事件的對象注冊到事件總線中,然后根據@Subscriber注解來查找對象中的訂閱方法,并且將這些訂閱方法和訂閱對象存儲在map中。當用戶在某個地方發布一個事件時,事件總線根據事件的參數類型和tag找到對應的訂閱者對象,最后執行訂閱者對象中的方法。這些訂閱方法會執行在用戶指定的線程模型中,比如mode=ThreadMode.ASYNC則表示該訂閱方法執行在子線程中,更多細節請看下面的說明。
下面我們先看看Subscriber 注解的定義:
[Subscriber.java](https://github.com/hehonghui/AndroidEventBus/blob/master/src/org/simple/eventbus/Subscriber.java)
~~~
/**
* 事件接收函數的注解類,運用在函數上
*
* @author mrsimple
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Subscriber {
/**
* 事件的tag,類似于BroadcastReceiver中的Action,事件的標識符
*
* @return
*/
String tag() default EventType.DEFAULT_TAG;
/**
* 事件執行的線程,默認為主線程
*
* @return
*/
ThreadMode mode() default ThreadMode.MAIN;
}
~~~
該注解作用于函數上,并且有一個tag 和mode ,分別為事件的tag (類似廣播接收器的Action )和該訂閱函數的執行線程。
在將訂閱對象注冊到事件總線時會找到所有使用了Subscriber 注解的類,并且以tag 和事件類型作為key,訂閱函數列表作為value 存儲在map 中,對應代碼如下:
[EventBus.java](https://github.com/hehonghui/AndroidEventBus/blob/master/src/org/simple/eventbus/EventBus.java)
~~~
package org.simple.eventbus;
import android.util.Log;
import org.simple.eventbus.handler.AsyncEventHandler;
import org.simple.eventbus.handler.DefaultEventHandler;
import org.simple.eventbus.handler.EventHandler;
import org.simple.eventbus.handler.UIThreadEventHandler;
import org.simple.eventbus.matchpolicy.DefaultMatchPolicy;
import org.simple.eventbus.matchpolicy.MatchPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* <p>
* EventBus是AndroidEventBus框架的核心類,也是用戶的入口類.它存儲了用戶注冊的訂閱者信息和方法,
* 事件類型和該事件對應的tag標識一個種類的事件{@see EventType},每一種事件對應有一個或者多個訂閱者{@see Subscription}
* ,訂閱者中的訂閱函數通過{@see Subcriber}注解來標識tag和線程模型,這樣使得用戶體檢較為友好,代碼也更加整潔.
* <p>
* 用戶需要在發布事件前通過@{@see #register(Object)}方法將訂閱者注冊到EventBus中,EventBus會解析該訂閱者中使用了
* {@see Subcriber}標識的函數,并且將它們以{@see EventType}為key,以{@see Subscription}
* 列表為value存儲在map中. 當用戶post一個事件時通過事件到map中找到對應的訂閱者,然后按照訂閱函數的線程模型將函數執行在對應的線程中.
* <p>
* 最后在不在需要訂閱事件時,應該調用{@see #unregister(Object)}函數注銷該對象,避免內存泄露!
* 例如在Activity或者Fragment的onDestory函數中注銷對Activity或者Fragment的訂閱.
* <p>
* 注意 : 如果發布的事件的參數類型是訂閱的事件參數的子類,訂閱函數默認也會被執行。例如你在訂閱函數中訂閱的是List<String>類型的事件,
* 但是在發布時發布的是ArrayList<String>的事件,
* 因此List<String>是一個泛型抽象,而ArrayList<String>才是具體的實現
* ,因此這種情況下訂閱函數也會被執行。如果你需要訂閱函數能夠接收到的事件類型必須嚴格匹配 ,你可以構造一個EventBusConfig對象,
* 然后設置MatchPolicy然后在使用事件總線之前使用該EventBusConfig來初始化事件總線. <code>
* EventBusConfig config = new EventBusConfig();
config.setMatchPolicy(new StrictMatchPolicy());
EventBus.getDefault().initWithConfig(config);
* </code>
*/
public final class EventBus {
private static final String DESCRIPTOR = EventBus.class.getSimpleName();
/**
* 事件總線描述符描述符
*/
private String mDesc = DESCRIPTOR;
private final Map<EventType, CopyOnWriteArrayList<Subscription>> mSubcriberMap = new ConcurrentHashMap<EventType, CopyOnWriteArrayList<Subscription>>();
private List<EventType> mStickyEvents = Collections
.synchronizedList(new LinkedList<EventType>());
ThreadLocal<Queue<EventType>> mLocalEvents = new ThreadLocal<Queue<EventType>>() {
protected java.util.Queue<EventType> initialValue() {
return new ConcurrentLinkedQueue<EventType>();
};
};
EventDispatcher mDispatcher = new EventDispatcher();
SubsciberMethodHunter mMethodHunter = new SubsciberMethodHunter(mSubcriberMap);
private static EventBus sDefaultBus;
private EventBus() {
this(DESCRIPTOR);
}
public EventBus(String desc) {
mDesc = desc;
}
public static EventBus getDefault() {
if (sDefaultBus == null) {
synchronized (EventBus.class) {
if (sDefaultBus == null) {
sDefaultBus = new EventBus();
}
}
}
return sDefaultBus;
}
/**
* 注冊訂閱對象
* @param subscriber
*/
public void register(Object subscriber) {
if (subscriber == null) {
return;
}
synchronized (this) {
mMethodHunter.findSubcribeMethods(subscriber);
}
}
/**
* 以sticky的形式注冊,則會在注冊成功之后迭代所有的sticky事件
*
* @param subscriber
*/
public void registerSticky(Object subscriber) {
this.register(subscriber);
// 處理sticky事件
mDispatcher.dispatchStickyEvents(subscriber);
}
public void unregister(Object subscriber) {
if (subscriber == null) {
return;
}
synchronized (this) {
mMethodHunter.removeMethodsFromMap(subscriber);
}
}
public void post(Object event) {
post(event, EventType.DEFAULT_TAG);
}
/**
* 發布事件
*
* @param event 要發布的事件
* @param tag 事件的tag, 類似于BroadcastReceiver的action
*/
public void post(Object event, String tag) {
if (event == null) {
Log.e(this.getClass().getSimpleName(), "The event object is null");
return;
}
mLocalEvents.get().offer(new EventType(event.getClass(), tag));
mDispatcher.dispatchEvents(event);
}
/**
* 發布Sticky事件,tag為EventType.DEFAULT_TAG
*
* @param event
*/
public void postSticky(Object event) {
postSticky(event, EventType.DEFAULT_TAG);
}
/**
* 發布含有tag的Sticky事件
*
* @param event 事件
* @param tag 事件tag
*/
public void postSticky(Object event, String tag) {
if (event == null) {
Log.e(this.getClass().getSimpleName(), "The event object is null");
return;
}
EventType eventType = new EventType(event.getClass(), tag);
eventType.event = event;
mStickyEvents.add(eventType);
}
public void removeStickyEvent(Class<?> eventClass) {
removeStickyEvent(eventClass, EventType.DEFAULT_TAG);
}
/**
* 移除Sticky事件
*
* @param type
*/
public void removeStickyEvent(Class<?> eventClass, String tag) {
Iterator<EventType> iterator = mStickyEvents.iterator();
while (iterator.hasNext()) {
EventType eventType = iterator.next();
if (eventType.paramClass.equals(eventClass)
&& eventType.tag.equals(tag)) {
iterator.remove();
}
}
}
public List<EventType> getStickyEvents() {
return mStickyEvents;
}
/**
* 設置訂閱函數匹配策略
*
* @param policy 匹配策略
*/
public void setMatchPolicy(MatchPolicy policy) {
mDispatcher.mMatchPolicy = policy;
}
/**
* 設置執行在UI線程的事件處理器
*
* @param handler
*/
public void setUIThreadEventHandler(EventHandler handler) {
mDispatcher.mUIThreadEventHandler = handler;
}
/**
* 設置執行在post線程的事件處理器
*
* @param handler
*/
public void setPostThreadHandler(EventHandler handler) {
mDispatcher.mPostThreadHandler = handler;
}
/**
* 設置執行在異步線程的事件處理器
*
* @param handler
*/
public void setAsyncEventHandler(EventHandler handler) {
mDispatcher.mAsyncEventHandler = handler;
}
/**
* 返回訂閱map
*
* @return
*/
public Map<EventType, CopyOnWriteArrayList<Subscription>> getSubscriberMap() {
return mSubcriberMap;
}
/**
* 獲取等待處理的事件隊列
*
* @return
*/
public Queue<EventType> getEventQueue() {
return mLocalEvents.get();
}
public synchronized void clear() {
mLocalEvents.get().clear();
mSubcriberMap.clear();
}
public String getDescriptor() {
return mDesc;
}
public EventDispatcher getDispatcher() {
return mDispatcher;
}
/**
* 事件分發器
*
* @author mrsimple
*/
private class EventDispatcher {
/**
* 將接收方法執行在UI線程
*/
EventHandler mUIThreadEventHandler = new UIThreadEventHandler();
/**
* 哪個線程執行的post,接收方法就執行在哪個線程
*/
EventHandler mPostThreadHandler = new DefaultEventHandler();
/**
* 異步線程中執行訂閱方法
*/
EventHandler mAsyncEventHandler = new AsyncEventHandler();
/**
* 緩存一個事件類型對應的可EventType列表
*/
private Map<EventType, List<EventType>> mCacheEventTypes
= new ConcurrentHashMap<EventType, List<EventType>>();
/**
* 事件匹配策略,根據策略來查找對應的EventType集合
*/
MatchPolicy mMatchPolicy = new DefaultMatchPolicy();
/**
* @param event
*/
void dispatchEvents(Object aEvent) {
Queue<EventType> eventsQueue = mLocalEvents.get();
while (eventsQueue.size() > 0) {
deliveryEvent(eventsQueue.poll(), aEvent);
}
}
/**
* 根據aEvent查找到所有匹配的集合,然后處理事件
*
* @param type
* @param aEvent
*/
private void deliveryEvent(EventType type, Object aEvent) {
// 如果有緩存則直接從緩存中取
List<EventType> eventTypes = getMatchedEventTypes(type, aEvent);
// 迭代所有匹配的事件并且分發給訂閱者
for (EventType eventType : eventTypes) {
handleEvent(eventType, aEvent);
}
}
/**
* 處理單個事件
*
* @param eventType
* @param aEvent
*/
private void handleEvent(EventType eventType, Object aEvent) {
List<Subscription> subscriptions = mSubcriberMap.get(eventType);
if (subscriptions == null) {
return;
}
for (Subscription subscription : subscriptions) {
final ThreadMode mode = subscription.threadMode;
EventHandler eventHandler = getEventHandler(mode);
// 處理事件
eventHandler.handleEvent(subscription, aEvent);
}
}
private List<EventType> getMatchedEventTypes(EventType type, Object aEvent) {
List<EventType> eventTypes = null;
// 如果有緩存則直接從緩存中取
if (mCacheEventTypes.containsKey(type)) {
eventTypes = mCacheEventTypes.get(type);
} else {
eventTypes = mMatchPolicy.findMatchEventTypes(type, aEvent);
mCacheEventTypes.put(type, eventTypes);
}
return eventTypes != null ? eventTypes : new ArrayList<EventType>();
}
void dispatchStickyEvents(Object subscriber) {
for (EventType eventType : mStickyEvents) {
handleStickyEvent(eventType, subscriber);
}
}
/**
* 處理單個Sticky事件
*
* @param eventType
* @param aEvent
*/
private void handleStickyEvent(EventType eventType, Object subscriber) {
List<EventType> eventTypes = getMatchedEventTypes(eventType, eventType.event);
// 事件
Object event = eventType.event;
for (EventType foundEventType : eventTypes) {
Log.e("", "### 找到的類型 : " + foundEventType.paramClass.getSimpleName()
+ ", event class : " + event.getClass().getSimpleName());
final List<Subscription> subscriptions = mSubcriberMap.get(foundEventType);
if (subscriptions == null) {
continue;
}
for (Subscription subItem : subscriptions) {
final ThreadMode mode = subItem.threadMode;
EventHandler eventHandler = getEventHandler(mode);
// 如果訂閱者為空,那么該sticky事件分發給所有訂閱者.否則只分發給該訂閱者
if (isTarget(subItem, subscriber)
&& (subItem.eventType.equals(foundEventType)
|| subItem.eventType.paramClass
.isAssignableFrom(foundEventType.paramClass))) {
// 處理事件
eventHandler.handleEvent(subItem, event);
}
}
}
}
/**
* 如果傳遞進來的訂閱者不為空,那么該Sticky事件只傳遞給該訂閱者(注冊時),
* 否則所有訂閱者都傳遞(發布時).
*
* @param item
* @param subscriber
* @return
*/
private boolean isTarget(Subscription item, Object subscriber) {
Object cacheObject = item.subscriber != null ? item.subscriber.get() : null;
return subscriber == null || (subscriber != null
&& cacheObject != null && cacheObject.equals(subscriber));
}
private EventHandler getEventHandler(ThreadMode mode) {
if (mode == ThreadMode.ASYNC) {
return mAsyncEventHandler;
}
if (mode == ThreadMode.POST) {
return mPostThreadHandler;
}
return mUIThreadEventHandler;
}
} // end of EventDispatcher
}
~~~
查找訂閱方法的工作交給了SubsciberMetbodHunter 類,我們看看相關的函數:
[SubsciberMethodHunter.java](https://github.com/hehonghui/AndroidEventBus/blob/master/src/org/simple/eventbus/SubsciberMethodHunter.java)
~~~
package org.simple.eventbus;
import android.util.Log;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
public class SubsciberMethodHunter {
Map<EventType, CopyOnWriteArrayList<Subscription>> mSubcriberMap;
public SubsciberMethodHunter(Map<EventType, CopyOnWriteArrayList<Subscription>> subscriberMap) {
mSubcriberMap = subscriberMap;
}
/**
* 查找訂閱對象中的所有訂閱函數,訂閱函數的參數只能有一個.找到訂閱函數之后構建Subscription存儲到Map中
*
* @param subscriber 訂閱對象
* @return
*/
public void findSubcribeMethods(Object subscriber) {
if (mSubcriberMap == null) {
throw new NullPointerException("the mSubcriberMap is null. ");
}
Class<?> clazz = subscriber.getClass();
// 查找類中符合要求的注冊方法,直到Object類
while (clazz != null && !isSystemCalss(clazz.getName())) {
final Method[] allMethods = clazz.getDeclaredMethods();
for (int i = 0; i < allMethods.length; i++) {
Method method = allMethods[i];
// 根據注解來解析函數
Subscriber annotation = method.getAnnotation(Subscriber.class);
if (annotation != null) {
// 獲取方法參數
Class<?>[] paramsTypeClass = method.getParameterTypes();
// 訂閱函數只支持一個參數
if (paramsTypeClass != null && paramsTypeClass.length == 1) {
Class<?> paramType = convertType(paramsTypeClass[0]);
EventType eventType = new EventType(paramType, annotation.tag());
TargetMethod subscribeMethod = new TargetMethod(method, eventType,
annotation.mode());
subscibe(eventType, subscribeMethod, subscriber);
}
}
} // end for
// 獲取父類,以繼續查找父類中符合要求的方法
clazz = clazz.getSuperclass();
}
}
/**
* 按照EventType存儲訂閱者列表,這里的EventType就是事件類型,一個事件對應0到多個訂閱者.
*
* @param event 事件
* @param method 訂閱方法對象
* @param subscriber 訂閱者
*/
private void subscibe(EventType event, TargetMethod method, Object subscriber) {
CopyOnWriteArrayList<Subscription> subscriptionLists = mSubcriberMap.get(event);
if (subscriptionLists == null) {
subscriptionLists = new CopyOnWriteArrayList<Subscription>();
}
Subscription newSubscription = new Subscription(subscriber, method);
if (subscriptionLists.contains(newSubscription)) {
return;
}
subscriptionLists.add(newSubscription);
// 將事件類型key和訂閱者信息存儲到map中
mSubcriberMap.put(event, subscriptionLists);
}
/**
* remove subscriber methods from map
*
* @param subscriber
*/
public void removeMethodsFromMap(Object subscriber) {
Iterator<CopyOnWriteArrayList<Subscription>> iterator = mSubcriberMap
.values().iterator();
while (iterator.hasNext()) {
CopyOnWriteArrayList<Subscription> subscriptions = iterator.next();
if (subscriptions != null) {
List<Subscription> foundSubscriptions = new
LinkedList<Subscription>();
Iterator<Subscription> subIterator = subscriptions.iterator();
while (subIterator.hasNext()) {
Subscription subscription = subIterator.next();
// 獲取引用
Object cacheObject = subscription.subscriber.get();
if (isObjectsEqual(cacheObject, subscriber)
|| cacheObject == null) {
Log.d("", "### 移除訂閱 " + subscriber.getClass().getName());
foundSubscriptions.add(subscription);
}
}
// 移除該subscriber的相關的Subscription
subscriptions.removeAll(foundSubscriptions);
}
// 如果針對某個Event的訂閱者數量為空了,那么需要從map中清除
if (subscriptions == null || subscriptions.size() == 0) {
iterator.remove();
}
}
}
private boolean isObjectsEqual(Object cachedObj, Object subscriber) {
return cachedObj != null
&& cachedObj.equals(subscriber);
}
private Class<?> convertType(Class<?> eventType) {
Class<?> returnClass = eventType;
if (eventType.equals(boolean.class)) {
returnClass = Boolean.class;
} else if (eventType.equals(int.class)) {
returnClass = Integer.class;
} else if (eventType.equals(float.class)) {
returnClass = Float.class;
} else if (eventType.equals(double.class)) {
returnClass = Double.class;
}
return returnClass;
}
private boolean isSystemCalss(String name) {
return name.startsWith("java.") || name.startsWith("javax.") || name.startsWith("android.");
}
}
~~~
這樣就將每個訂閱對象的所有訂閱函數存儲在一個表中了, 這個key 就是EventType ,而EventType 又由訂閱函數的參數類型和tag 決定,當發布一個事件時,就從表中獲得訂閱了這個事件的所有訂閱函數列表,然后將它們執行在指定的線程。
發布事件的代碼如下:
~~~
public final class EventBus {
.............
ThreadLocal<Queue<EventType>> mLocalEvents = new ThreadLocal<Queue<EventType>>() {
protected java.util.Queue<EventType> initialValue() {
return new ConcurrentLinkedQueue<EventType>();
};
};
EventDispatcher mDispatcher = new EventDispatcher();
............
/**
* post a event
* @param event
*/
public void post(Object event) {
post(event, EventType.DEFAULT_TAG);
}
/**
* 發布事件
*
* @param event 要發布的事件
* @param tag 事件的tag, 類似于BroadcastReceiver的action
*/
public void post(Object event, String tag) {
if (event == null) {
Log.e(this.getClass().getSimpleName(), "The event object is null");
return;
}
mLocalEvents.get().offer(new EventType(event.getClass(), tag));
mDispatcher.dispatchEvents(event);
}
...........
}
~~~
可以看到,在發布事件時,首先將事件添加到mLocalEvents 這個事件隊列中,然后通過EventDispatcher 來對事件進行處理,例如,根據EventType 找到訂閱者列表,根據訂閱者列表的線程模型找到對應的事件處理器,最后通過事件處理器執行訂閱函數,相關代碼如下:
~~~
public final class EventBus {
.............
ThreadLocal<Queue<EventType>> mLocalEvents = new ThreadLocal<Queue<EventType>>() {
protected java.util.Queue<EventType> initialValue() {
return new ConcurrentLinkedQueue<EventType>();
};
};
EventDispatcher mDispatcher = new EventDispatcher();
............
/**
* 事件分發器
*
* @author mrsimple
*/
private class EventDispatcher {
//將接收方法執行在UI線程
EventHandler mUIThreadEventHandler = new UIThreadEventHandler();
//哪個線程執行的post,接收方法就執行在哪個線程
EventHandler mPostThreadHandler = new DefaultEventHandler();
// 異步線程中執行訂閱方法
EventHandler mAsyncEventHandler = new AsyncEventHandler();
// 緩存一個事件類型對應的可EventType列表
private Map<EventType, List<EventType>> mCacheEventTypes = new ConcurrentHashMap<EventType, List<EventType>>();
// 事件匹配策略,根據策略來查找對應的EventType集合
MatchPolicy mMatchPolicy = new DefaultMatchPolicy();
void dispatchEvents(Object aEvent) {
Queue<EventType> eventsQueue = mLocalEvents.get();
while (eventsQueue.size() > 0) {
deliveryEvent(eventsQueue.poll(), aEvent);
}
}
/**
* 根據aEvent查找到所有匹配的集合,然后處理事件
*
* @param type
* @param aEvent
*/
private void deliveryEvent(EventType type, Object aEvent) {
// 如果有緩存則直接從緩存中取
List<EventType> eventTypes = getMatchedEventTypes(type, aEvent);
// 迭代所有匹配的事件并且分發給訂閱者
for (EventType eventType : eventTypes) {
handleEvent(eventType, aEvent);
}
}
/**
* 處理單個事件
*
* @param eventType
* @param aEvent
*/
private void handleEvent(EventType eventType, Object aEvent) {
List<Subscription> subscriptions = mSubcriberMap.get(eventType);
if (subscriptions == null) {
return;
}
// 將事件分發到所有的訂閱者中,也就是執行訂閱函數
for (Subscription subscription : subscriptions) {
final ThreadMode mode = subscription.threadMode;
// 根據線程模型來獲取對應的事件處理器
EventHandler eventHandler = getEventHandler(mode);
// 處理事件
eventHandler.handleEvent(subscription, aEvent);
}
}
private List<EventType> getMatchedEventTypes(EventType type, Object aEvent) {
List<EventType> eventTypes = null;
// 如果有緩存則直接從緩存中取
if (mCacheEventTypes.containsKey(type)) {
eventTypes = mCacheEventTypes.get(type);
} else {
eventTypes = mMatchPolicy.findMatchEventTypes(type, aEvent);
mCacheEventTypes.put(type, eventTypes);
}
return eventTypes != null ? eventTypes : new ArrayList<EventType>();
}
void dispatchStickyEvents(Object subscriber) {
for (EventType eventType : mStickyEvents) {
handleStickyEvent(eventType, subscriber);
}
}
/**
* 處理單個Sticky事件
*
* @param eventType
* @param aEvent
*/
private void handleStickyEvent(EventType eventType, Object subscriber) {
List<EventType> eventTypes = getMatchedEventTypes(eventType, eventType.event);
// 事件
Object event = eventType.event;
for (EventType foundEventType : eventTypes) {
Log.e("", "### 找到的類型 : " + foundEventType.paramClass.getSimpleName()
+ ", event class : " + event.getClass().getSimpleName());
final List<Subscription> subscriptions = mSubcriberMap.get(foundEventType);
if (subscriptions == null) {
continue;
}
for (Subscription subItem : subscriptions) {
final ThreadMode mode = subItem.threadMode;
EventHandler eventHandler = getEventHandler(mode);
// 如果訂閱者為空,那么該sticky事件分發給所有訂閱者.否則只分發給該訂閱者
if (isTarget(subItem, subscriber)
&& (subItem.eventType.equals(foundEventType)
|| subItem.eventType.paramClass
.isAssignableFrom(foundEventType.paramClass))) {
// 處理事件
eventHandler.handleEvent(subItem, event);
}
}
}
}
/**
* 如果傳遞進來的訂閱者不為空,那么該Sticky事件只傳遞給該訂閱者(注冊時),否則所有訂閱者都傳遞(發布時).
*
* @param item
* @param subscriber
* @return
*/
private boolean isTarget(Subscription item, Object subscriber) {
Object cacheObject = item.subscriber != null ? item.subscriber.get() : null;
return subscriber == null || (subscriber != null
&& cacheObject != null && cacheObject.equals(subscriber));
}
private EventHandler getEventHandler(ThreadMode mode) {
if (mode == ThreadMode.ASYNC) {
return mAsyncEventHandler;
}
if (mode == ThreadMode.POST) {
return mPostThreadHandler;
}
return mUIThreadEventHandler;
}
} // end of EventDispatcher
}
~~~
發布事件之后會將事件添加到事件列表中,會根據事件類型和tag 構造EventType,發布的事件是一個,但是EventType 可能有多個,例如,用戶在注冊訂閱函數時參數類型為`List<String>`,那在用戶發布事件時可能參數就會傳遞ArrayList<String>類型。因此,在查找訂閱函數時會將參數類型是發布事件類型的父類也返回,這樣使得在訂閱事件參數類型與發布類型之間有父子關系的情況下也能正常匹配到。
找到了對應的EventType 之后,就會根據這個EventType 從表中獲得所有的訂閱者,然后根據這些訂閱者的線程模型找到一個對應的事件處理器,最后將這個訂閱函數執行到對應的線程中。至此,整個訂閱一一發布流程完畢。當然,與廣播接收器類似,不要忘記在Activity 等對象的生命周期結束時,調用EventBus 的unregister 函數來注銷,否則會造成內存泄露!