EventBus 源碼分析

基本使用

//註冊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;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章