BroadcastReceiver
? 本質(zhì)上是一個(gè)監(jiān)聽器捆交,分為接收者和發(fā)送者淑翼。用于監(jiān)聽(接收)應(yīng)用發(fā)出的廣播消息,并做出響應(yīng)品追⌒ǎ可用于進(jìn)程間通信、線程間通信和監(jiān)聽系統(tǒng)的特定時(shí)間(如:電話呼入肉瓦,網(wǎng)絡(luò)狀態(tài)變更等)遭京。
使用觀察者模式:基于消息的發(fā)布/訂閱事件模型。
常用做與android 系統(tǒng)事件的監(jiān)聽和交互泞莉。
消耗時(shí)間哪雕、空間較多,在onRecieve()方法內(nèi)可以獲得Context和Intent參數(shù)鲫趁,通過這兩個(gè)方法斯嚎,可以調(diào)用AndroidSDK中的很多方法,屬于重量級組件挨厚。
可跨進(jìn)程通信堡僻。
Eventbus
? 針對android跨進(jìn)程、線程通信的優(yōu)化方案疫剃,一定程度上可以代替廣播钉疫、handler、Intent慌申。
優(yōu)點(diǎn)
- 調(diào)度靈活陌选,不依賴于context理郑。
- 可繼承。
- 有事件優(yōu)先級咨油。
- 粘性事件機(jī)制您炉。
- 量級較輕。
1. 實(shí)現(xiàn)原理
-
getDefault():通過懶漢單例模式獲取到對象
public static EventBus getDefault() { if (defaultInstance == null) { synchronized (EventBus.class) { if (defaultInstance == null) { defaultInstance = new EventBus(); } } } return defaultInstance; }
在new對象時(shí)役电,使用builder模式:
EventBus(EventBusBuilder builder) { subscriptionsByEventType = new HashMap<>(); typesBySubscriber = new HashMap<>(); stickyEvents = new ConcurrentHashMap<>(); mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10); backgroundPoster = new BackgroundPoster(this); asyncPoster = new AsyncPoster(this); indexCount = builder.subscriberInfoIndexes != null ? builder.subscriberInfoIndexes.size() : 0; subscriberMethodFinder = new SubscriberMethodFinder(builder.subscriberInfoIndexes, builder.strictMethodVerification, builder.ignoreGeneratedIndex); logSubscriberExceptions = builder.logSubscriberExceptions; logNoSubscriberMessages = builder.logNoSubscriberMessages; sendSubscriberExceptionEvent = builder.sendSubscriberExceptionEvent; sendNoSubscriberEvent = builder.sendNoSubscriberEvent; throwSubscriberException = builder.throwSubscriberException; eventInheritance = builder.eventInheritance; executorService = builder.executorService; }
-
register()實(shí)現(xiàn)如下:
public void register(Object subscriber) { Class<?> subscriberClass = subscriber.getClass(); List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//通過反射的方式獲取到所有通過注解注冊的回調(diào)方法 synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod);//這里是具體的注冊方法 } } }
Subscribe():
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { Class<?> eventType = subscriberMethod.eventType;//獲取觸發(fā)本次消費(fèi)的事件類型 Subscription newSubscription = new Subscription(subscriber, subscriberMethod);//創(chuàng)建訂閱對象(把注冊者和事件消費(fèi)方法綁定) CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType); if (subscriptions == null) { subscriptions = new CopyOnWriteArrayList<>(); subscriptionsByEventType.put(eventType, subscriptions); } else { if (subscriptions.contains(newSubscription)) {//若該事件(注冊者和消費(fèi)方法)已注冊赚爵,則拋異常 throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event " + eventType); } } int size = subscriptions.size(); for (int i = 0; i <= size; i++) { if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {//輪詢的目的是為了按照優(yōu)先級插入到指定的位置(事件消費(fèi)隊(duì)列) subscriptions.add(i, newSubscription); break; } } List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);//獲取該訂閱者下的所有訂閱事件 if (subscribedEvents == null) { subscribedEvents = new ArrayList<>(); typesBySubscriber.put(subscriber, subscribedEvents); } subscribedEvents.add(eventType);//將本事件添加進(jìn)觸發(fā)事件列表中 if (subscriberMethod.sticky) {//粘性事件處理 if (eventInheritance) { // Existing sticky events of all subclasses of eventType have to be considered. // Note: Iterating over all events may be inefficient with lots of sticky events, // thus data structure should be changed to allow a more efficient lookup // (e.g. an additional map storing sub classes of super classes: Class -> List<Class>). Set<Map.Entry<Class<?>, Object>> entries = stickyEvents.entrySet(); for (Map.Entry<Class<?>, Object> entry : entries) { Class<?> candidateEventType = entry.getKey(); if (eventType.isAssignableFrom(candidateEventType)) { Object stickyEvent = entry.getValue(); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } } else { Object stickyEvent = stickyEvents.get(eventType); checkPostStickyEventToSubscription(newSubscription, stickyEvent); } } }
以上就是EventBus注冊時(shí)的邏輯,接下來我們看看發(fā)布事件的時(shí)候的邏輯:
-
post():
public void post(Object event) { PostingThreadState postingState = currentPostingThreadState.get(); List<Object> eventQueue = postingState.eventQueue;//獲取當(dāng)前線程的消息隊(duì)列 eventQueue.add(event);//將本事件添加進(jìn)消息隊(duì)列中 if (!postingState.isPosting) {//若當(dāng)前 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)遍歷事件隊(duì)列(在這兒可以類比handler機(jī)制不過不是死循環(huán)法瑟,也不存在阻塞冀膝,每post一次就進(jìn)行判斷,是否處于posting) postSingleEvent(eventQueue.remove(0), postingState);//主要的消費(fèi)邏輯 } } finally { postingState.isPosting = false; postingState.isMainThread = false; } } }
這個(gè)currentPostingThreadState是做什么的呢霎挟,我們可以看一下它的聲明和實(shí)現(xiàn):
private final ThreadLocal<PostingThreadState> currentPostingThreadState = new ThreadLocal<PostingThreadState>() { @Override protected PostingThreadState initialValue() { return new PostingThreadState(); } };
這里使用了ThreadLocal窝剖,說明在每個(gè)線程里都會(huì)有這個(gè)對象的副本。我們接著往下看PostingThreadState是維護(hù)什么的類:
final static class PostingThreadState { final List<Object> eventQueue = new ArrayList<Object>();//事件隊(duì)列酥夭,用一個(gè)list維護(hù) boolean isPosting;//是否在發(fā)布事件(就是之后的循環(huán)遍歷是否在執(zhí)行) boolean isMainThread;//是否為主線程赐纱,通過判斷當(dāng)前l(fā)ooper是否為MainLooper Subscription subscription;//當(dāng)前的訂閱類,上面有說明 Object event;//當(dāng)前正在處理的事件 boolean canceled;//當(dāng)前事件是否被取消 }
我們繼續(xù)看postSingleEvent()方法熬北,這里是事件消費(fèi)的主要邏輯:
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error { Class<?> eventClass = event.getClass(); boolean subscriptionFound = false; if (eventInheritance) { List<Class<?>> eventTypes = lookupAllEventTypes(eventClass); int countTypes = eventTypes.size(); for (int h = 0; h < countTypes; h++) { Class<?> clazz = eventTypes.get(h); subscriptionFound |= postSingleEventForEventType(event, postingState, clazz); } } else { subscriptionFound = postSingleEventForEventType(event, postingState, eventClass); } if (!subscriptionFound) { if (logNoSubscriberMessages) { Log.d(TAG, "No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { post(new NoSubscriberEvent(this, event)); } } }
這里可以看到最終都會(huì)回調(diào)postSingleEventForEventType()這個(gè)方法疙描,我們繼續(xù)看這個(gè)方法:
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass) { CopyOnWriteArrayList<Subscription> subscriptions; synchronized (this) { subscriptions = subscriptionsByEventType.get(eventClass); } if (subscriptions != null && !subscriptions.isEmpty()) { for (Subscription subscription : subscriptions) { postingState.event = event;//當(dāng)前正在處理的事件 postingState.subscription = subscription;//當(dāng)前正在輪詢的訂閱事件 boolean aborted = false; try { postToSubscription(subscription, event, postingState.isMainThread);//事件處理方法 aborted = postingState.canceled; } finally { postingState.event = null; postingState.subscription = null; postingState.canceled = false; } if (aborted) { break; } } return true; } return false; }
我們接著看:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) { switch (subscription.subscriberMethod.threadMode) {//這里就是處理線程模式的不同策略 case POSTING: invokeSubscriber(subscription, event); break; case MAIN: if (isMainThread) { invokeSubscriber(subscription, event); } else { mainThreadPoster.enqueue(subscription, event); } break; case BACKGROUND: if (isMainThread) { backgroundPoster.enqueue(subscription, event); } else { invokeSubscriber(subscription, event); } break; case ASYNC: asyncPoster.enqueue(subscription, event); break; default: throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode); } }
我們從默認(rèn)的POSTING模式往下看:
void invokeSubscriber(PendingPost pendingPost) { Object event = pendingPost.event; Subscription subscription = pendingPost.subscription; PendingPost.releasePendingPost(pendingPost); if (subscription.active) { invokeSubscriber(subscription, event); } }
我們接著看:
void invokeSubscriber(Subscription subscription, Object event) { try { subscription.subscriberMethod.method.invoke(subscription.subscriber, event);//最終是通過反射的方法調(diào)用事件的處理 } catch (InvocationTargetException e) { handleSubscriberException(subscription, event, e.getCause()); } catch (IllegalAccessException e) { throw new IllegalStateException("Unexpected exception", e); } }
這樣我們可以知道,最后調(diào)用方法是通過反射來調(diào)用與之對應(yīng)的消費(fèi)事件的方法讶隐。