對源碼的閱讀不多,從用的比較多的EventBus開始,還是有些看不懂的地方。
最常用的寫法:
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
EventBus.getDefault().post("hello");
@Subscribe
public void mainEvent(MessageEvent messageEvent) {
if(messageEvent.getmStrMessage().equals(CommonEventMessage.LOGINED)) {
mIMainView.updateMessage();
}
}
1.EventBus.getDefault().register(this);
1.1 getDefault():
/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
if (defaultInstance == null) {
synchronized (EventBus.class) {
if (defaultInstance == null) {
defaultInstance = new EventBus();
}
}
}
return defaultInstance;
}
這裡就是一個單例的模式:首先直接做null的判斷操作,如果為null了才去進行同步鎖的操作,保證了性能。
接下來是加入了同步鎖,防止多線程的幹擾,但在
defaultInstance = new EventBus();
這裡會産生一個問題,就是重排序的問題,目前這個已經進入的線程在進行執行個體化的時候,會發生三件事:
- 給 instance 配置設定記憶體
- 調用 Singleton 的構造函數來初始化成員變量
- 将instance對象指向配置設定的記憶體空間(執行完這步 instance 就為非 null 了)
但是由于指令重排序,2和3的步驟可能發生颠倒,是以要對defaultInstance添加volatile關鍵字來避免這種情況:
static volatile EventBus defaultInstance;
1.2 register()
/**
* Registers the given subscriber to receive events. Subscribers must call {@link #unregister(Object)} once they
* are no longer interested in receiving events.
* <p/>
* Subscribers have event handling methods that must be annotated by {@link Subscribe}.
* The {@link Subscribe} annotation also allows configuration like {@link
* ThreadMode} and priority.
*/
public void register(Object subscriber) {
Class<?> subscriberClass = subscriber.getClass();
List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
subscribe(subscriber, subscriberMethod);
}
}
}
List<SubscriberMethod> findSubscriberMethods(Class<?> subscriberClass) {
List<SubscriberMethod> subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
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;
}
}
利用反射去查找目前類是否有接收訂閱的方法,如果沒有的話,則會抛出一個錯誤異常出來。然後把查找出來的方法進行一次周遊,然後添加訂閱。
2.EventBus.getDefault().unregister(this)
/** Unregisters the given subscriber from all event classes. */
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());
}
}
參考
如何正确地寫出單例模式
秒懂,Java 注解 (Annotation)你可以這樣學
深入淺出反射