EventBus 源碼分析
分析源碼之前
EventBus 大神的 github烂叔,最好的老師皆看。
一、使用
我們?cè)谄綍r(shí)都會(huì)運(yùn)用 EventBus 去簡(jiǎn)化各個(gè)組件之間的通信痒给,相信使用了它之后感覺(jué)是真的方便了不少灰署,可以有效的對(duì)解耦發(fā)送方和接收方甥郑。
無(wú)論主線程中調(diào)用子線程的方法渗钉,還是子線程中調(diào)用主線程的方法郭厌,我們不必去寫(xiě)繁雜的 Handler ,也省去了內(nèi)存泄漏等的麻煩你踩。
首先我們簡(jiǎn)單的運(yùn)用一下 EventBus诅岩。
1、添加依賴(lài)
implementation 'org.greenrobot:eventbus:3.1.1'
2姓蜂、定義事件
public class Student {
private String name;
private String addr;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
3按厘、準(zhǔn)備訂閱者
聲明并注釋您的訂閱方法医吊,可選擇指定一個(gè)線程模型钱慢。
@Subscribe(threadMode = ThreadMode.MAIN)
public void showSutednt(Student student) {
Toast.makeText(this, student.toString(), Toast.LENGTH_SHORT).show();
}
4、注冊(cè)和注銷(xiāo)訂閱者
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
5卿堂、發(fā)布事件
Student student = new Student();
student.setAddr("北京");
student.setName("張三");
EventBus.getDefault().post(student);
二束莫、使用須知
1懒棉、基于「發(fā)布訂閱」
首先我們要明白它是基于「發(fā)布訂閱」模式,通過(guò) 發(fā)布者 「Publisher」 發(fā)布事件給 「EventBus」 览绿,EventBus 最后把事件分發(fā)給訂閱者 「Subscriber」 策严。<br />
2、四種線程模型
- POSTING (默認(rèn)) :事件處理函數(shù)的線程和發(fā)布事件的線程在同一個(gè)線程饿敲。也就是直接操作妻导。
- MAIN :事件處理函數(shù)的線程是主線程。注意不能有耗時(shí)操作怀各。
- BACKGROUND:事件處理函數(shù)在后臺(tái)線程(只有一個(gè)后臺(tái)線程)倔韭。
- ASYNC:無(wú)論事件發(fā)布的函數(shù)在哪里,始終會(huì)新建一個(gè)新線程來(lái)運(yùn)行瓢对。
分析源碼
一寿酌、EventBus 的創(chuàng)建
EventBus#getDefault()
public static EventBus getDefault() {
if (defaultInstance == null) {
Class var0 = EventBus.class;
synchronized(EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
這是最常用最經(jīng)典的 DoubleCheck 單例模式來(lái)創(chuàng)建 EventBus 對(duì)象。
EventBus#EventBus()
public EventBus() {
this(DEFAULT_BUILDER);
}
EventBus#EventBus(EventBusBuilder builder)
EventBus(EventBusBuilder builder) {
this.currentPostingThreadState = new ThreadLocal<EventBus.PostingThreadState>() {
protected EventBus.PostingThreadState initialValue() {
return new EventBus.PostingThreadState();
}
};
this.logger = builder.getLogger();
this.subscriptionsByEventType = new HashMap();
this.typesBySubscriber = new HashMap();
this.stickyEvents = new ConcurrentHashMap();
this.mainThreadSupport = builder.getMainThreadSupport();
this.mainThreadPoster = this.mainThreadSupport != null ? this.mainThreadSupport.createPoster(this) : null;
this.backgroundPoster = new BackgroundPoster(this);
this.asyncPoster = new AsyncPoster(this);
this.indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0;
this.subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex);
this.logSubscriberExceptions = builder.logSubscriberExceptions;
this.logNoSubscriberMessages = builder.logNoSubscriberMessages;
this.sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent;
this.sendNoSubscriberEvent = builder.sendNoSubscriberEvent;
this.throwSubscriberException = builder.throwSubscriberException;
this.eventInheritance = builder.eventInheritance;
this.executorService = builder.executorService;
}
同樣也是常用的 Builder 設(shè)計(jì)模式 來(lái)構(gòu)造 EventBus 對(duì)象硕蛹。
我們需要重點(diǎn)注意的幾個(gè)參數(shù)
HashMap 「 subscriptionsByEventType」
HashMap 「typesBySubscriber」
ConcurrentHashMap 「stickyEvents」
SubscriberMethodFinder 「subscriberMethodFinder」
Poster 「mainThreadPoster」
BackgroundPoster 「 backgroundPoster」
AsyncPoster 「asyncPoster」
具體作用我們往下分析醇疼。
二、register
1法焰、register
EventBusBuilder#register(Object subscriber)
public void register(Object subscriber) {
//首先獲取 subscriber 的 Class 對(duì)象
Class<?> subscriberClass = subscriber.getClass();
//查找所有訂閱者內(nèi)部的事件方法
List<SubscriberMethod> subscriberMethods = this.subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized(this) {
Iterator var5 = subscriberMethods.iterator();
while(var5.hasNext()) {
SubscriberMethod subscriberMethod = (SubscriberMethod)var5.next();
// 調(diào)用 subscribe 分發(fā)訂閱者的事件方法
this.subscribe(subscriber, subscriberMethod);
}
}
}
從這里可以看到我們?cè)?Activity 里進(jìn)行注冊(cè)的時(shí)候秧荆,實(shí)際是把 Activity 作為訂閱者去注冊(cè)。<br />首先獲取 subscriber 的 Class 對(duì)象壶栋,然后通過(guò) findSubscriberMethods 查詢(xún)?cè)谶@個(gè)訂閱者類(lèi)里擁有 EventBus 注解的方法辰如,然后添加到 List<SubscriberMethod> subscriberMethods。然后依次調(diào)用 subscribe贵试。
2、findSubscriberMethods
SubscriberMethodFinder#findSubscriberMethods
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//首先看看 METHOD_CACHE 緩存中有沒(méi)有毙玻,查找過(guò)的會(huì)保存在 METHOD_CACHE 緩存
//詳解2.1 解釋 SubscriberMethod
List<SubscriberMethod> subscriberMethods = (List)METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
} else {
//一般 ignoreGeneratedIndex 默認(rèn) false 看名字應(yīng)該是通過(guò)反射來(lái)查找
if (this.ignoreGeneratedIndex) {
subscriberMethods = this.findUsingReflection(subscriberClass);
} else {
subscriberMethods = this.findUsingInfo(subscriberClass);
}
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass + " and its super classes have no public methods with the @Subscribe annotation");
} else {
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
}
詳解 2.1
SubscriberMethod 是 一個(gè)包裝類(lèi)豌蟋,把方法,線程模式桑滩,事件類(lèi)梧疲,優(yōu)先級(jí),是否粘性运准,方法名稱(chēng) 包裝起來(lái)幌氮。方便我們使用。
public class SubscriberMethod {
final Method method;
final ThreadMode threadMode;
final Class<?> eventType;
final int priority;
final boolean sticky;
String methodString;
···省略
}
3胁澳、findUsingReflection
SubscriberMethodFinder#findUsingReflection
private List<SubscriberMethod> findUsingReflection(Class<?> subscriberClass) {
// 詳解 3.1
SubscriberMethodFinder.FindState findState = this.prepareFindState();
// 詳解 3.2
findState.initForSubscriber(subscriberClass);
//findState.clazz 也就是 subscriberClass
while(findState.clazz != null) {
//詳解 3.3 把查找的信息保存在 findState 中
this.findUsingReflectionInSingleClass(findState);
findState.moveToSuperclass();
}
return this.getMethodsAndRelease(findState);
}
詳解 3.1
FindState 是查找結(jié)果類(lèi)该互,包含 SubscriberMethod 的集合 subscriberMethods,也就是這個(gè)訂閱者 class 里所有的訂閱事件方法韭畸。還有 通過(guò) 事件類(lèi)型 為 key 保存方法的 HashMap anyMethodByEventType宇智,也就是把該事件類(lèi)型的所有方法放到這個(gè) HashMap 里蔓搞。而 subscriberClassByMethodKey 是以方法名為 key,保存訂閱者類(lèi)的 HashMap随橘。具體詳細(xì)作用需要往下繼續(xù)分析喂分。
static class FindState {
final List<SubscriberMethod> subscriberMethods = new ArrayList();
final Map<Class, Object> anyMethodByEventType = new HashMap();
final Map<String, Class> subscriberClassByMethodKey = new HashMap();
final StringBuilder methodKeyBuilder = new StringBuilder(128);
Class<?> subscriberClass;
Class<?> clazz;
boolean skipSuperClasses;
SubscriberInfo subscriberInfo;
··· 省略
}
FindState 的創(chuàng)建運(yùn)用了數(shù)組大小為4的緩存池,當(dāng) FIND_STATE_POOL[i] 不為空的時(shí)候那么就使用這個(gè)對(duì)象机蔗,然后 FIND_STATE_POOL[i] 置為 null蒲祈。
private SubscriberMethodFinder.FindState prepareFindState() {
SubscriberMethodFinder.FindState[] var1 = FIND_STATE_POOL;
synchronized(FIND_STATE_POOL) {
for(int i = 0; i < 4; ++i) {
SubscriberMethodFinder.FindState state = FIND_STATE_POOL[i];
if (state != null) {
FIND_STATE_POOL[i] = null;
return state;
}
}
return new SubscriberMethodFinder.FindState();
}
}
詳解 3.2
對(duì) FindState 進(jìn)行 subscriberClass 等賦值和初始化
void initForSubscriber(Class<?> subscriberClass) {
this.subscriberClass = this.clazz = subscriberClass;
this.skipSuperClasses = false;
this.subscriberInfo = null;
}
詳解 3.3
通過(guò)反射獲取 擁有 EventBus 注解的方法
private void findUsingReflectionInSingleClass(SubscriberMethodFinder.FindState findState) {
Method[] methods;
try {
//通過(guò)反射獲取訂閱者類(lèi)里所有的方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable var12) {
//如果有權(quán)限問(wèn)題 那么就獲取 除了私有方法外的所有方法
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
Method[] var3 = methods;
int var4 = methods.length;
for(int var5 = 0; var5 < var4; ++var5) {
Method method = var3[var5];
//獲取方法修飾符
int modifiers = method.getModifiers();
//修飾符是否是 public 是否可以被忽略
if ((modifiers & 1) != 0 && (modifiers & 5192) == 0) {
//獲得方法的參數(shù)
Class<?>[] parameterTypes = method.getParameterTypes();
//我們只需要看 參數(shù)個(gè)數(shù)是 1
if (parameterTypes.length == 1) {
//獲取注解 Subscribe
Subscribe subscribeAnnotation = (Subscribe)method.getAnnotation(Subscribe.class);
//如果有
if (subscribeAnnotation != null) {
//拿到 參數(shù)的類(lèi)型 也就是 事件的類(lèi)型
Class<?> eventType = parameterTypes[0];
//詳解 3.4
if (findState.checkAdd(method, eventType)) {
ThreadMode threadMode = subscribeAnnotation.threadMode();
//把查找到的方法,事件類(lèi)型萝嘁,線程類(lèi)型讳嘱,優(yōu)先級(jí),是否粘性 放入包裝類(lèi) SubscriberMethod 中酿愧。
//最后添加到 subscriberMethods
//循環(huán)往復(fù) 最后把所有的方法以及它的包裝類(lèi)的所有信息都放入了查找結(jié)果類(lèi) findState 沥潭。
findState.subscriberMethods.add(new SubscriberMethod(method, eventType, threadMode, subscribeAnnotation.priority(), subscribeAnnotation.sticky()));
}
}
} else if (this.strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException("@Subscribe method " + methodName + "must have exactly 1 parameter but has " + parameterTypes.length);
}
} else if (this.strictMethodVerification && method.isAnnotationPresent(Subscribe.class)) {
String methodName = method.getDeclaringClass().getName() + "." + method.getName();
throw new EventBusException(methodName + " is a illegal @Subscribe method: must be public, non-static, and non-abstract");
}
}
}
詳解 3.4
判斷 是否可以把 這個(gè)方法 放到訂閱方法集合。
boolean checkAdd(Method method, Class<?> eventType) {
//往 anyMethodByEventType 添加 key 類(lèi)型 eventType 的嬉挡,value 是 method钝鸽。
//把事件的類(lèi)型和方法放到這個(gè)HashMap 中。 其實(shí)就是保證 同一個(gè) eventType 對(duì)應(yīng)一個(gè)方法
//如果 key 沒(méi)有重復(fù)則 返回 null 庞钢,如果已經(jīng)有值了返回 之前的值
Object existing = this.anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
//如果子類(lèi)和父類(lèi)都去訂閱該事件 那么 existing 不等于 null
if (existing instanceof Method) {
if (!this.checkAddWithMethodSignature((Method)existing, eventType)) {
throw new IllegalStateException();
}
this.anyMethodByEventType.put(eventType, this);
}
//那么我們?cè)趺慈ヌ砑?重復(fù)的呢拔恰?就需要根據(jù)方法的簽名去了 詳情在下面
return this.checkAddWithMethodSignature(method, eventType);
}
}
private boolean checkAddWithMethodSignature(Method method, Class<?> eventType) {
this.methodKeyBuilder.setLength(0);
this.methodKeyBuilder.append(method.getName());
this.methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = this.methodKeyBuilder.toString();
Class<?> methodClass = method.getDeclaringClass();
//subscriberClassByMethodKey HashMap 是以 方法 為 key ,methodClass 為 value。
//一個(gè)方法對(duì)應(yīng)一個(gè) methodClass
Class<?> methodClassOld = (Class)this.subscriberClassByMethodKey.put(methodKey, methodClass);
//class1.isAssignableFrom(class2) 判定此 Class 對(duì)象所表示的類(lèi)或接口與指定的 Class
//參數(shù)所表示的類(lèi)或接口是否相同基括,或是否是其超類(lèi)或超接口颜懊。
//如果在同一個(gè)類(lèi) 不同方法名 那么返回 methodClassOld== null 直接返回 true
//如果是 同一個(gè)方法名,那么就看看這個(gè)方法所在的類(lèi)是否有有親屬關(guān)系了风皿,如果沒(méi)有 那么就返回 false河爹,不會(huì)添加
//如果是 同一個(gè)方法名 但是是父類(lèi)或者接口,那么返回 true桐款,最后替換 anyMethodByEventType 的方法值
if (methodClassOld != null && !methodClassOld.isAssignableFrom(methodClass)) {
this.subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
} else {
return true;
}
}
一個(gè) eventType 對(duì)應(yīng)一個(gè)方法咸这,一個(gè)方法對(duì)應(yīng)一個(gè) methodClass 。<br />我們具體怎么理解 anyMethodByEventType 和 subscriberClassByMethodKey 呢魔眨?<br />我們?nèi)绾未_定同一個(gè) eventType 對(duì)應(yīng)一個(gè)方法媳维?anyMethodByEventType 負(fù)責(zé)存放這個(gè)鍵值對(duì),如果有兩個(gè)方法參數(shù)都是同一個(gè) eventType遏暴,那么就需要用 subscriberClassByMethodKey 去保證了侄刽。看一看方法名是否相同朋凉,不相同那么就替換州丹,如果相同那么就看是否是父類(lèi)的這個(gè)方法也訂閱了,如果是那么也是替換侥啤,如果不是就不會(huì)替換当叭。
到此為止我們已經(jīng)找到所有 EventBus 標(biāo)注的方法了。接下來(lái)應(yīng)該 subscribe(subscriber, subscriberMethod) 方法了盖灸∫媳睿看看這些方法是如何被注冊(cè)的。
4赁炎、subscribe
EventBus#subscribe
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//獲取 訂閱方法的 eventType 也就是事件 class
Class<?> eventType = subscriberMethod.eventType;
//創(chuàng)建 訂閱 封裝類(lèi)
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
// private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//這個(gè) Map 通過(guò) eventType 獲取 所有的訂閱集合
//Subscription 詳解 4.1
CopyOnWriteArrayList<Subscription> subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventType);
//如果 subscriptions 為空 那么新建 并添加 到 subscriptionsByEventType
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList();
this.subscriptionsByEventType.put(eventType, subscriptions);
//如果 里面有這個(gè) 訂閱封裝類(lèi) 那么報(bào)錯(cuò) 這個(gè)類(lèi)已經(jīng)有這個(gè) 事件的訂閱了醉箕,不能重復(fù)訂閱
} else if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
}
int size = subscriptions.size();
//按照 priority 優(yōu)先級(jí)來(lái)插入集合中
for(int i = 0; i <= size; ++i) {
if (i == size || subscriberMethod.priority > ((Subscription)subscriptions.get(i)).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
// 同一訂閱者中 typeClass 的集合 用來(lái)判斷 這個(gè)方法是否是粘性的
List<Class<?>> subscribedEvents = (List)this.typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList();
this.typesBySubscriber.put(subscriber, subscribedEvents);
}
((List)subscribedEvents).add(eventType);
//如果接收sticky事件,立即分發(fā)sticky事件
if (subscriberMethod.sticky) {
//默認(rèn)情況下 event 事件允許繼承,即默認(rèn)情況下eventInheritance==true
if (this.eventInheritance) {
Set<Entry<Class<?>, Object>> entries = this.stickyEvents.entrySet();
Iterator var9 = entries.iterator();
while(var9.hasNext()) {
Entry<Class<?>, Object> entry = (Entry)var9.next();
Class<?> candidateEventType = (Class)entry.getKey();
//這里就是看 eventType 是否是 candidateEventType 類(lèi) 或者 candidateEventType 的父類(lèi) 徙垫、接口
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
this.checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
//如果不允許繼承 那么直接就是這個(gè) eventType class
Object stickyEvent = this.stickyEvents.get(eventType);
//這個(gè)最后走的是 postToSubscription 方法讥裤,我們下面會(huì)具體分析
this.checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
詳解 4.1
Subscription 封裝了 subscriber 訂閱者 和 subscriberMethod 訂閱方法 ,以及這個(gè)訂閱的是否 acitive 姻报。
final class Subscription {
final Object subscriber;
final SubscriberMethod subscriberMethod;
volatile boolean active;
···
}
我們來(lái)看一下 subscriptionsByEventType 和 typesBySubscriber 又是兩個(gè) Map己英。
subscriptionsByEventType 是根據(jù) tpyeClass 的查找 subscriptions,也就是根據(jù)事件類(lèi)型來(lái)找 訂閱集合的吴旋。這個(gè)集合有著優(yōu)先級(jí)损肛,同一事件,不同優(yōu)先級(jí)的 subscription荣瑟。
typesBySubscriber 是跟劇 訂閱者 查找 tpyeClass治拿,也就是根據(jù)訂閱者查找其中的事件,如果有粘性的就立馬分發(fā)笆焰。
到此 register 就分析完畢劫谅,說(shuō)實(shí)話(huà)這樣分析下來(lái),腦袋里實(shí)在還是不懂這個(gè)流程嚷掠,那我們就換一下流程圖捏检,簡(jiǎn)化一下這個(gè)流程。
三不皆、post
我們?nèi)绾伟延嗛喺叩姆椒ê陀嗛喪录嚓P(guān)聯(lián)未檩,也就是事件是如何分發(fā)到事件方法的。
首先我們需要了解 「currentPostingThreadState」 在不同線程中保存 「PostingThreadState」粟焊。
private final ThreadLocal<EventBus.PostingThreadState> currentPostingThreadState;
「PostingThreadState」 是分發(fā)線程狀態(tài)冤狡,包換 事件隊(duì)列 、是否正在分發(fā)项棠、是否在主線程悲雳、是否取消了 還有訂閱分裝類(lèi) Subscription ,以及當(dāng)前事件香追。記錄著本線程中事件分發(fā)的狀態(tài)合瓢。
static final class PostingThreadState {
final List<Object> eventQueue = new ArrayList();
boolean isPosting;
boolean isMainThread;
Subscription subscription;
Object event;
boolean canceled;
PostingThreadState() {
}
}
public void post(Object event) {
EventBus.PostingThreadState postingState = (EventBus.PostingThreadState)this.currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
//把當(dāng)前 event 添加到 eventQueue
eventQueue.add(event);
//如果時(shí)間沒(méi)有正在分發(fā)
if (!postingState.isPosting) {
//對(duì) postingState 進(jìn)行賦值
postingState.isMainThread = this.isMainThread();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
//依次 取出 event 并執(zhí)行 postSingleEvent 方法。
while(!eventQueue.isEmpty()) {
this.postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
//最后對(duì) postingState 做 默認(rèn)值 處理
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
通過(guò)方法命名我們知道這是處理單個(gè)事件的方法透典。
1晴楔、postSingleEvent
EventBus#postSingleEvent
private void postSingleEvent(Object event, EventBus.PostingThreadState postingState) throws Error {
//首先獲取這個(gè)類(lèi)的 class 對(duì)象
Class<?> eventClass = event.getClass();
//是否查找到了 訂閱方法
boolean subscriptionFound = false;
//如果允許繼承
if (this.eventInheritance) {
//查找該類(lèi) 以及它的父類(lèi) 的所有 事件類(lèi)型
List<Class<?>> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
//如果發(fā)現(xiàn)有匹配的事件類(lèi)型??
for(int h = 0; h < countTypes; ++h) {
Class<?> clazz = (Class)eventTypes.get(h);
subscriptionFound |= this.postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = this.postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (this.logNoSubscriberMessages) {
this.logger.log(Level.FINE, "No subscribers registered for event " + eventClass);
}
if (this.sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) {
this.post(new NoSubscriberEvent(this, event));
}
}
}
2顿苇、postSingleEventForEventType
private boolean postSingleEventForEventType(Object event, EventBus.PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList subscriptions;
synchronized(this) {
//獲得該 eventClass 的所有 訂閱方法
subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
Iterator var5 = subscriptions.iterator();
while(var5.hasNext()) {
//從 方法集合中取出一個(gè) 方法
Subscription subscription = (Subscription)var5.next();
//給 postingState 賦值
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
//這回終于要 分發(fā)成功了
this.postToSubscription(subscription, event, postingState.isMainThread);
aborted = postingState.canceled;
} finally {
postingState.event = null;
postingState.subscription = null;
postingState.canceled = false;
}
if (aborted) {
break;
}
}
return true;
} else {
return false;
}
}
3、postToSubscription
終于有看到這個(gè)方法税弃,在 subscrible 方法的粘性事件處理上 也是調(diào)用的這個(gè)方法纪岁,這也是我們真正分發(fā)的方法。
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
//首先判斷 是哪種 threadMode 模式 運(yùn)行
switch(subscription.subscriberMethod.threadMode) {
case POSTING:
//詳解 3.1
this.invokeSubscriber(subscription, event);
break;
case MAIN:
//詳解 3.2
if (isMainThread) {
this.invokeSubscriber(subscription, event);
} else {
this.mainThreadPoster.enqueue(subscription, event);
}
break;
case MAIN_ORDERED:
if (this.mainThreadPoster != null) {
this.mainThreadPoster.enqueue(subscription, event);
} else {
this.invokeSubscriber(subscription, event);
}
break;
case BACKGROUND:
//詳解 3.3
if (isMainThread) {
this.backgroundPoster.enqueue(subscription, event);
} else {
this.invokeSubscriber(subscription, event);
}
break;
case ASYNC:
//詳解 3.4
this.asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
詳解 3.1
EventBus#invokeSubscriber
void invokeSubscriber(Subscription subscription, Object event) {
try {
subscription.subscriberMethod.method.invoke(subscription.subscriber, event);
} catch (InvocationTargetException var4) {
this.handleSubscriberException(subscription, event, var4.getCause());
} catch (IllegalAccessException var5) {
throw new IllegalStateException("Unexpected exception", var5);
}
}
最后我們發(fā)現(xiàn) invokeSubscriber 方法實(shí)際是通過(guò) subscription 的持有的 method 的引用通過(guò)反射的方法则果,把 訂閱者 subscriber 和 事件 event 填入幔翰,真正調(diào)用的就是 subscriber.xxx(event)。也就是 activity.xxx(event)西壮。
饒了一大圈遗增,其實(shí)也就是把 訂閱者 和 事件的 引用保存起來(lái),查找方法款青,通過(guò)反射進(jìn)行調(diào)用做修。真是原理很簡(jiǎn)單,實(shí)現(xiàn)很蛋疼抡草,不把你繞暈是不行的缓待。
詳解 3.2
如果 是在主線程中,isMainThread == true渠牲,直接 invokeSubscriber 旋炒。<br />如果 false ,那么就需要 倒一手了签杈。其實(shí) HandlerPoster 就是 一個(gè) Handler 瘫镇, 并且它的 Lopper 是主線程的Looper 。這樣就是通過(guò) Handler 答姥,添加到主線程了铣除,然后執(zhí)行 invokeSubscriber 。這么看切換線程原理還是 Handler鹦付。
HandlerPoster#enqueue
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized(this) {
this.queue.enqueue(pendingPost);
if (!this.handlerActive) {
this.handlerActive = true;
if (!this.sendMessage(this.obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
詳解 3.3
BackgroundPoster 和 主線程的 HandlerPoster 不通尚粘,它是一個(gè) Runnable 線程。和主線程 HandlerPoster 不同的是它會(huì)把 queue 的所有 pendingPost 都去執(zhí)行敲长。
final class BackgroundPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
private volatile boolean executorRunning;
BackgroundPoster(EventBus eventBus) {
this.eventBus = eventBus;
this.queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized(this) {
this.queue.enqueue(pendingPost);
if (!this.executorRunning) {
this.executorRunning = true;
this.eventBus.getExecutorService().execute(this);
}
}
}
public void run() {
try {
while(true) {
PendingPost pendingPost = this.queue.poll(1000);
if (pendingPost == null) {
synchronized(this) {
pendingPost = this.queue.poll();
if (pendingPost == null) {
this.executorRunning = false;
return;
}
}
}
this.eventBus.invokeSubscriber(pendingPost);
}
} catch (InterruptedException var9) {
this.eventBus.getLogger().log(Level.WARNING, Thread.currentThread().getName() + " was interruppted", var9);
} finally {
this.executorRunning = false;
}
}
}
詳解 3.4
AsyncPoster 是一個(gè) Runnalbe郎嫁。是通過(guò)線程池產(chǎn)生新的線程,最后執(zhí)行 invokeSubscriber 方法祈噪。和 BackgroundPoster 不同的是 一次只取一個(gè) PendingPost泽铛。
class AsyncPoster implements Runnable, Poster {
private final PendingPostQueue queue;
private final EventBus eventBus;
AsyncPoster(EventBus eventBus) {
this.eventBus = eventBus;
this.queue = new PendingPostQueue();
}
public void enqueue(Subscription subscription, Object event) {
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
this.queue.enqueue(pendingPost);
this.eventBus.getExecutorService().execute(this);
}
public void run() {
PendingPost pendingPost = this.queue.poll();
if (pendingPost == null) {
throw new IllegalStateException("No pending post available");
} else {
this.eventBus.invokeSubscriber(pendingPost);
}
}
}
//最后還是走的 invokeSubscriber 方法
void invokeSubscriber(PendingPost pendingPost) {
Object event = pendingPost.event;
Subscription subscription = pendingPost.subscription;
PendingPost.releasePendingPost(pendingPost);
if (subscription.active) {
this.invokeSubscriber(subscription, event);
}
}
最后也要來(lái)一個(gè)流程圖來(lái)總結(jié)下 post 的流程。
四辑鲤、 unregister
解綁訂閱者和訂閱事件盔腔。
public synchronized void unregister(Object subscriber) {
//獲取 該 訂閱者 的所有 訂閱事件
List<Class<?>> subscribedTypes = (List)this.typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
Iterator var3 = subscribedTypes.iterator();
while(var3.hasNext()) {
Class<?> eventType = (Class)var3.next();
//挨個(gè) 解綁 訂閱者 和 訂閱事件的關(guān)系
this.unsubscribeByEventType(subscriber, eventType);
}
//最后把這個(gè) 訂閱者 移出 該 map
this.typesBySubscriber.remove(subscriber);
} else {
this.logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
//獲取 這個(gè)訂閱事件的 所有訂閱者
List<Subscription> subscriptions = (List)this.subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for(int i = 0; i < size; ++i) {
Subscription subscription = (Subscription)subscriptions.get(i);
//判斷 是否是這個(gè)訂閱者 subscription 置 flase ,然后 移除 該集合
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
--i;
--size;
}
}
}
}
總結(jié)
一、regist
1弛随、遍歷所有 EventBus 的訂閱事件瓢喉。<br />2、把 封裝訂閱者加入 以事件類(lèi)型為 key 舀透,所有封裝訂閱者的集合為 values 的 Map 中栓票。詳細(xì)見(jiàn)注釋。<br />3盐杂、把訂閱事件 添加到 以 「subscriber」訂閱者為 key,「subscribedEvents」訂閱事件集合為 value 的 Map 中哆窿。<br />4链烈、如果訂閱了粘性事件的訂閱者,那么會(huì) 粘性事件集合中獲取之前的粘性事件挚躯,然后相應(yīng)這些粘性事件强衡。
注釋?zhuān)?lt;br />把 「subscriber」和 「subscriberMethod」封裝成 「Subscription」 封裝訂閱者。通過(guò) 訂閱事件的 「SubscriberMethod」 獲取 「eventType」码荔,以 eventType 事件類(lèi)型為 key 漩勤,封裝訂閱者集合(subscriptions)為 value 的 Map 「subscriptionsByEventType」。并把這個(gè) Subscription 添加到 subscriptions 中缩搅。
二越败、post
1、獲取該線程下的事件隊(duì)列硼瓣。<br />2究飞、把要發(fā)送的事件添加到隊(duì)列中。<br />3堂鲤、根據(jù)訂閱事件 查找所有 封裝訂閱者亿傅。<br />4、根據(jù)訂閱方法的執(zhí)行模式瘟栖,在對(duì)應(yīng)的線程中通過(guò)反射執(zhí)行訂閱者的訂閱方法葵擎。
三、unregist
1半哟、首先 獲取訂閱者的所有訂閱事件酬滤。<br />2、遍歷 訂閱事件 <br />3寓涨、根據(jù) 訂閱事件獲取 訂閱者的集合敏晤。<br />4、判斷 該訂閱者 是否在 封裝訂閱者集合 「subscriptions」中缅茉,把這個(gè)訂閱者從 subscriptions 中移除嘴脾。<br />5、最后 把訂閱者 從「typesBySubscriber」中移除。
最后
「云開(kāi)方見(jiàn)日译打,潮盡爐峰出耗拓。」——戴叔倫