基于eventbus 2.4.0
項(xiàng)目中很多地方用到EventBus
大體的使用 就是這樣的幾段代碼
// 注冊(cè)
EventBus.getDefault().register(this);
// 發(fā)送
EventBus.getDefault().post(new Event());
// 響應(yīng)
public void onEventMainThread(Event event) {
}
// 取消注冊(cè)
EventBus.getDefault().unregister(this);
EventBus.getDefault()
利用單例模式獲取的是EventBus實(shí)例。
register
方法
// 采用的是訂閱者模式
private synchronized void register(Object subscriber, boolean sticky, int priority) {
// findSubscriberMethods 通過反射獲取subscriber的 onEventMainThread方法
List<SubscriberMethod> subscriberMethods = this.subscriberMethodFinder.findSubscriberMethods(subscriber.getClass());
// 獲取迭代器
Iterator i$ = subscriberMethods.iterator();
// 遍歷訂閱
while(i$.hasNext()) {
SubscriberMethod subscriberMethod = (SubscriberMethod)i$.next();
// 訂閱
this.subscribe(subscriber, subscriberMethod, sticky, priority);
}
}
SubscriberMethod
類中保存了 響應(yīng)Method
訂閱方法里是怎么做的授账?大體思路是按照優(yōu)先級(jí)把一個(gè)個(gè)Subscription對(duì)象(包含注冊(cè)對(duì)象)放入EventType對(duì)應(yīng)的List中迄沫,再把注冊(cè)對(duì)象的EventType放到對(duì)應(yīng)的List中开睡。
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod, boolean sticky, int priority) {
Class<?> eventType = subscriberMethod.eventType;
CopyOnWriteArrayList<Subscription> subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventType);
// 利用訂閱者對(duì)象和響應(yīng)方法創(chuàng)建一個(gè)新的對(duì)象
Subscription newSubscription = new Subscription(subscriber, subscriberMethod, priority);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList();
this.subscriptionsByEventType.put(eventType, subscriptions);
} else if (subscriptions.contains(newSubscription)) {
// 一個(gè)對(duì)象只允許注冊(cè)一次
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType);
}
int size = subscriptions.size();
// 添加到此事件對(duì)應(yīng)的list里
for(int i = 0; i <= size; ++i) {
if (i == size || newSubscription.priority > ((Subscription)subscriptions.get(i)).priority) {
subscriptions.add(i, newSubscription);
break;
}
}
// 通過注冊(cè)的對(duì)象 獲取注冊(cè)的event類對(duì)象
List<Class<?>> subscribedEvents = (List)this.typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList();
this.typesBySubscriber.put(subscriber, subscribedEvents);
}
((List)subscribedEvents).add(eventType);
if (sticky) {
// sticky 默認(rèn)false 暫時(shí)不研究
Map var11 = this.stickyEvents;
Object stickyEvent;
synchronized(this.stickyEvents) {
stickyEvent = this.stickyEvents.get(eventType);
}
if (stickyEvent != null) {
this.postToSubscription(newSubscription, stickyEvent, Looper.getMainLooper() == Looper.myLooper());
}
}
}
取消注冊(cè)大體就是反過來清空纷责。
復(fù)雜的是發(fā)送事件的過程吆寨,涉及到線程切換推姻。
public void post(Object event) {
EventBus.PostingThreadState postingState = (EventBus.PostingThreadState)this.currentPostingThreadState.get();
List<Object> eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while(!eventQueue.isEmpty()) {
// // 不斷循環(huán)來發(fā)送事件
this.postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
重點(diǎn)看 postSingleEvent
主要是把注冊(cè)對(duì)象的EventType對(duì)應(yīng)的List中取出窃款,然后根據(jù)不同的線程進(jìn)行分發(fā)课兄。
private void postSingleEvent(Object event, EventBus.PostingThreadState postingState) throws Error {
Class<?> eventClass = event.getClass();
boolean subscriptionFound = false;
if (this.eventInheritance) {
// 遍歷父類event 默認(rèn)false
List<Class<?>> eventTypes = this.lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for(int h = 0; h < countTypes; ++h) {
Class<?> clazz = (Class)eventTypes.get(h);
subscriptionFound |= this.postSingleEventForEventType(event, postingState, clazz);
}
} else {
// 繼續(xù)調(diào)用postSingleEventForEventType執(zhí)行
subscriptionFound = this.postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (this.logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (this.sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) {
this.post(new NoSubscriberEvent(this, event));
}
}
}
重點(diǎn)是 postSingleEventForEventType
根據(jù)不同的線程分發(fā)
private boolean postSingleEventForEventType(Object event, EventBus.PostingThreadState postingState, Class<?> eventClass) {
CopyOnWriteArrayList subscriptions;
synchronized(this) {
// 獲取event對(duì)應(yīng)的 所有注冊(cè)過的對(duì)象
subscriptions = (CopyOnWriteArrayList)this.subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
Iterator i$ = subscriptions.iterator();
while(i$.hasNext()) {
// 遍歷分發(fā)事件執(zhí)行postToSubscription
Subscription subscription = (Subscription)i$.next();
postingState.event = event;
postingState.subscription = subscription;
boolean aborted = false;
try {
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;
}
}
重點(diǎn)是 postToSubscription
根據(jù)訂閱方法指定的threadMode信息來執(zhí)行不同的分發(fā)。
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) {
switch(subscription.subscriberMethod.threadMode) {
case PostThread:
this.invokeSubscriber(subscription, event);
break;
case MainThread:
if (isMainThread) {
this.invokeSubscriber(subscription, event);
} else {
this.mainThreadPoster.enqueue(subscription, event);
}
break;
case BackgroundThread:
if (isMainThread) {
this.backgroundPoster.enqueue(subscription, event);
} else {
this.invokeSubscriber(subscription, event);
}
break;
case Async:
this.asyncPoster.enqueue(subscription, event);
break;
default:
throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode);
}
}
mainThreadPoster
繼承自Handler
晨继,當(dāng)調(diào)用它的enqueue
方法的時(shí)候烟阐,發(fā)送一個(gè)事件并在它自身的handleMessage
方法中從隊(duì)列中取值并進(jìn)行處理,從而達(dá)到在主線程中分發(fā)事件的目的。backgroundPoster也是同理蜒茄。