#### **前言**
有时候,在工作的过程中用到了广播接收器,用广播接收器的原因是小民需要在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设定了一些目标,如表所示。
![](https://box.kancloud.cn/b7e40df13b218323494b5200bb5473a7_1017x218.jpg)
打算**使用注解的形式实现事件总线**,这样用户在使用时比较方便,并且让接收函数可以执行在异步线程。当然,这个库的定制化、灵活性也是要求之一。大体思路如下:
在需要接收事件的对象初始化时将自身注册到事件总线中,事件总线会遍历这个对象的所属类中的所有函数,然后根据订阅函数的事件参数和@Subscriber 注解的tag 值构建一个EventType ,这个EventType 标识了一种事件类型,以这个EventType 为key ,订阅对象列表为value 构建一个map,存储这整个事件一一订阅者表,当通过EventBus 发布事件时, 会根据事件类型和tag 来构建一个EventType ,再根据这个EventType 到表中查找所有的订阅者,然后执行它们的订阅函数。如图所示。
![](https://box.kancloud.cn/0abcd9c2237257ec8f3e3aa5f4a93458_468x353.jpg)
详情参考[AndroidEventBus](https://github.com/hehonghui/AndroidEventBus)
#### **基本结构**
![基本结构](https://camo.githubusercontent.com/f1e9b092ec5fec24ce604efdc9e394dcd30f233e/687474703a2f2f696d672e626c6f672e6373646e2e6e65742f3230313530343236323233303430373839)
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 函数来注销,否则会造成内存泄露!