天天看點

閱讀EventBus源碼(筆記)待續1.EventBus.getDefault().register(this);2.EventBus.getDefault().unregister(this)參考

對源碼的閱讀不多,從用的比較多的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();
           

這裡會産生一個問題,就是重排序的問題,目前這個已經進入的線程在進行執行個體化的時候,會發生三件事:

  1. 給 instance 配置設定記憶體
  2. 調用 Singleton 的構造函數來初始化成員變量
  3. 将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)你可以這樣學

深入淺出反射