概述
EventBus基於安卓優化的發布-訂閱事件總線,本質上還是Java的觀察者模式。消息接收者注冊到Bus總線,消息發送后根據相應的消息類型分發消息。
總的注冊和消息發送流程如下
源碼解讀
觀察者注冊
使用單例模式新建唯一EventBus實例
public static EventBus getDefault() { EventBus instance = defaultInstance; if (instance == null) { synchronized (EventBus.class) { instance = EventBus.defaultInstance; if (instance == null) { instance = EventBus.defaultInstance = new EventBus(); } } } return instance; }
注冊觀察者
public void register(Object subscriber) { Class<?> subscriberClass = subscriber.getClass();//獲取觀察者的類 List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);//使用反射拿到觀察者類所有的監聽對象 synchronized (this) { for (SubscriberMethod subscriberMethod : subscriberMethods) { subscribe(subscriber, subscriberMethod);//訂閱該對象和它的所有方法 } } }
訂閱的時候按監聽方法參數分類緩存到Bus總線
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) { ... Class<?> eventType = subscriberMethod.eventType; Subscription newSubscription = new Subscription(subscriber, subscriberMethod); ... }
消息發送
消息發送者通過post發送消息
public void post(Object event) { PostingThreadState postingState = currentPostingThreadState.get(); List<Object> eventQueue = postingState.eventQueue; eventQueue.add(event); if (!postingState.isPosting) { postingState.isMainThread = isMainThread(); 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; } } }
拿到消息發送者發送消息的類型
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) { logger.log(Level.FINE, "No subscribers registered for event " + eventClass); } if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class && eventClass != SubscriberExceptionEvent.class) { post(new NoSubscriberEvent(this, event)); } } }
使用反射方法的invoke方法喚起觀察者的監聽方法
void invokeSubscriber(Subscription subscription, Object event) { try { subscription.subscriberMethod.method.invoke(subscription.subscriber, event);//最后用反射喚起對象的監聽方法 } catch (InvocationTargetException e) { handleSubscriberException(subscription, event, e.getCause()); } catch (IllegalAccessException e) { throw new IllegalStateException("Unexpected exception", e); } }
反注冊
根據觀察者的類型移除事件總線中相應的觀察者對象
public synchronized void unregister(Object subscriber) { List<Class<?>> subscribedTypes = typesBySubscriber.get(subscriber); if (subscribedTypes != null) { for (Class<?> eventType : subscribedTypes) { unsubscribeByEventType(subscriber, eventType); } typesBySubscriber.remove(subscriber); } else { logger.log(Level.WARNING, "Subscriber to unregister was not registered before: " + subscriber.getClass()); } }
總結
- 由於使用注解,在實際業務開發中可能定位Bug有困難
- 使用方便,比Handler和廣播方便
- 關鍵代碼使用反射,性能可能有所下降