基本使用
//註冊EventBus
EventBus.getDefault().register(this);
//發送事件
EventBus.getDefault().post(new FirstEvent("nihao-->"));
//接受事件回調方法
@Subscribe
public void onMainEvent(FirstEvent eventBean)
{
Toast.makeText(this,"FirstEvent--> "+eventBean.msg,Toast.LENGTH_SHORT).show();
Log.d(TAG,"FirstEvent ");
}
//反註冊EventBus
EventBus.getDefault().unregister(this);
源碼分析
//DCL 獲取EventBus單例
public static EventBus getDefault()
{
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();
//eventTypesCache 以eventType 爲key,該類的接口與繼承父類爲value,主要是爲了將所有關聯的事件關係保存在表裏面,進行事件繼承的消息通知
private static final Map<Class<?>, List<Class<?>>> eventTypesCache = new HashMap<>();
//以事件類型爲 key ,訂閱列表 Subscription爲value的一張map,
private final Map<Class<?>, CopyOnWriteArrayList<Subscription>> subscriptionsByEventType;
//以訂閱者Subscriber 爲key,以事件列表爲value的map表
private final Map<Object, List<Class<?>>> typesBySubscriber;
//粘貼性事件表
private final Map<Class<?>, Object> stickyEvents;
public EventBus()
{
this(DEFAULT_BUILDER);
}
EventBus(EventBusBuilder builder)
{
subscriptionsByEventType = new HashMap<>();
typesBySubscriber = new HashMap<>();
stickyEvents = new ConcurrentHashMap<>();
//主線程 post
mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
//後臺線程 post
backgroundPoster = new BackgroundPoster(this);
//異步線程 post
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;
}
** EventBus#register 註銷方法 **
//看看比較重要的註冊方法
public void register(Object subscriber)
{
//得到訂閱者的類
Class<?> subscriberClass = subscriber.getClass();
//從subscriberMethodFinder集合裏面去查找訂閱該類裏面的方法
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
//遍歷進行訂閱
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
** EventBus#subscribe **
// Must be called in synchronized block
//這裏其實就是通過類型EventType 放 Subscription 集合
// 通過 subscriber 放類型 EventType 集合
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod)
{
Class<?> eventType = subscriberMethod.eventType;
//Subscription二次封裝了訂閱者對象和 subscriberMethod,並且put到 CopyOnWriteArrayList 集合。
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//CopyOnWriteArrayList 適用於多線程併發操作,集合中存儲的對象是已訂閱者劃分的
//每個相同的eventType對應一個CopyOnWriteArrayList 集合
CopyOnWriteArrayList<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//subscriptions 不爲null代表有相同訂閱事件類型的 Subscription 對象。
//如果在相同訂閱事件類型前提下,訂閱對象和訂閱方法完全一樣,就拋異常。Subscription對象中有具體的 equals()判斷方法
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//根據註釋中的 priority 值大小對相同訂閱事件類型的 newSubscription 進行排序,
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//typesBySubscriber 每個訂閱對象對應一個集合
List<Class<?>> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
Log.d("wangjian", "subscriber = "+subscriber.getClass().getName()+", eventType = "+eventType.getName()+", subscribedEvents = "+subscribedEvents.size());
//判斷方法註釋中sticky值是否爲true,默認爲false
if (subscriberMethod.sticky) {
//只有在註冊之前調用了postSticky()方法,下面的post纔會有效
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>).
//如果class A extends B,A 事件爲粘性事件,參數爲 A 和 B訂閱方法都能能收到 A 對象的消息。
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 {
//eventInheritance = false情況,參數爲 B 的註釋方法是收不到消息的。
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
** SubscriberMethodFinder#findSubscriberMethods **
private static final Map<Class<?>, List<SubscriberMethod>> METHOD_CACHE = new ConcurrentHashMap<>();
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
//先從METHOD_CACHE緩存中取出列表,沒有的話就通過對象參數找出對應的訂閱方法列表。
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
//通過默認的方式實例化EventBus,ignoreGeneratedIndex爲false
if (ignoreGeneratedIndex) {
//利用反射方法得到訂閱方法列表
subscriberMethods = findUsingReflection(subscriberClass);
} else {
//這個比較難,暫時還沒學習。利用編譯時查找訂閱事件的方式完成,高端
subscriberMethods = 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;
}
}
** EventBus#unregister 反註銷方法 **
public synchronized void unregister(Object subscriber)
{
//通過subscriber 拿到 subscribedTypes 列表
List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
for (Class<?> eventType : subscribedTypes) {
//遍歷解除綁定
unsubscribeByEventType(subscriber, eventType);
}
// 從 typesBySubscriber 表中移除掉
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
//解除 key:eventType Value:subscriber 的Map表裏面的元素
private void unsubscribeByEventType(Object subscriber, Class<?> eventType) {
List<Subscription> subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
** EventBus#post 發送事件方法 **
//post方法
public void post(Object event)
{
PostingThreadState postingState = 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()) {
//如果事件隊列不爲空,進行事件發送,
postSingleEvent(eventQueue.remove(0), postingState);
}
}
finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
//postSingleEvent 方法
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);
//將這些查找到的class與subscriptionsByEventType集合中的key進行匹配,併發送
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));
}
}
}
//postSingleEventForEventType
private boolean postSingleEventForEventType(Object event, PostingThreadState postingState, Class<?> eventClass)
{
CopyOnWriteArrayList<Subscription> subscriptions;
synchronized (this) {
//從subscriptionsByEventType集合中查找是否存在這個事件
subscriptions = subscriptionsByEventType.get(eventClass);
}
if (subscriptions != null && !subscriptions.isEmpty()) {
//遍歷發送
for (Subscription subscription : subscriptions) {
postingState.event = event;
postingState.subscription = subscription;
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;
}
//postToSubscription 主要是線程選擇後通過反射調用和異步執行在對應的線程
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread)
{
//通過 threadMode 確定應該在哪條線程中發送消息
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);
}
}
** 看看主線程的切換執行 HandlerPoster **
//Looper爲主線程 最大消息處理時間是10ms
HandlerPoster mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
//HandlerPoster 是繼承 Handler 主線程消息處理
class HandlerPoster extends Handler
// 主線程任務執行隊列
private final PendingPostQueue queue;
//加入主線程 執行
void enqueue(Subscription subscription, Object event)
{
//將subscription 和 消息事件對象封裝到 PendingPost 中。
PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
synchronized (this) {
//加入隊列
queue.enqueue(pendingPost);
if (!handlerActive) {
handlerActive = true;
//發送消息通知
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
}
}
}
//消息的處理
@Override
public void handleMessage(Message msg)
{
boolean rescheduled = false;
try {
long started = SystemClock.uptimeMillis();
//死循環 循環去除隊列數據
while (true) {
//從隊列中取出 PendingPost 通過eventBus 對象直接發送。
//每次取出一個 header,會將下一個待發送 PendingPost 賦值給 header,直到發送完
//從執行隊列裏面去除一個post對象
PendingPost pendingPost = queue.poll();
if (pendingPost == null) {
synchronized (this) {
// Check again, this time in synchronized
pendingPost = queue.poll();
if (pendingPost == null) {
handlerActive = false;
return;
}
}
}
//在主線程裏面進行反射調用對應的方法
eventBus.invokeSubscriber(pendingPost);
//在規定時間內沒發送完,退出本次任務,重新執行handleMessage()接着發送
long timeInMethod = SystemClock.uptimeMillis() - started;
if (timeInMethod >= maxMillisInsideHandleMessage) {
if (!sendMessage(obtainMessage())) {
throw new EventBusException("Could not send handler message");
}
rescheduled = true;
//退出
return;
}
}
}
finally {
handlerActive = rescheduled;
}
}