Eventbus3代碼分析(五):getDefault()驳糯,register和EventBusBuilder等


EventBus getDefault()入口

除了注解东抹,其他都和EventBus這個類有關系了
我們先從getDefault()方法開始分析


入口分析

這里的getDefault()靜態(tài)方法帕识,很容易看出潜腻,是一個
線程加鎖的懶漢單例
具體通過new EventBus() 來創(chuàng)建實例

public static EventBus getDefault() {
    if (defaultInstance == null) {
        synchronized (EventBus.class) {
            if (defaultInstance == null) {
                defaultInstance = new EventBus();
            }
        }
    }
    return defaultInstance;
}

具體EventBus()構造

我們可以發(fā)現(xiàn)窍育,具體的構造卡睦,其實是
初始化一些Map值,引用類蔫骂,EventBusBuilder中的實現(xiàn)傳遞給EventBus類
其他的類么翰,慢慢分析

EventBus(EventBusBuilder builder) {
    subscriptionsByEventType = new HashMap<>();
    typesBySubscriber = new HashMap<>();
    stickyEvents = new ConcurrentHashMap<>();
    mainThreadPoster = new HandlerPoster(this, Looper.getMainLooper(), 10);
    backgroundPoster = new BackgroundPoster(this);
    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;
}

這里EventBusBuilder,只是一個 餓漢單例
在類創(chuàng)建之前辽旋,就已經(jīng)創(chuàng)建出來了

private static final EventBusBuilder DEFAULT_BUILDER = new EventBusBuilder();

而構造的賦值浩嫌,只是把 Builder中的值傳遞到本類中


對應的EventBusBuilder對象

我們觀察下面對應的EventBusBuilder類
有1個默認的線程池,管理線程
有很多boolean類型的變量补胚,存儲默認boolean屬性
有2個List码耐,分別存儲Class<?>類型 和
EventBusBuilder

public class EventBusBuilder {
    private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool();

    boolean logSubscriberExceptions = true;
    boolean logNoSubscriberMessages = true;
    boolean sendSubscriberExceptionEvent = true;
    boolean sendNoSubscriberEvent = true;
    boolean throwSubscriberException;
    boolean eventInheritance = true;
    boolean ignoreGeneratedIndex;
    boolean strictMethodVerification;
    ExecutorService executorService = DEFAULT_EXECUTOR_SERVICE;
    List<Class<?>> skipMethodVerificationForClasses;
    List<SubscriberInfoIndex> subscriberInfoIndexes;

    EventBusBuilder() {
    }

    /** Default: true */
    public EventBusBuilder logSubscriberExceptions(boolean logSubscriberExceptions) {
        this.logSubscriberExceptions = logSubscriberExceptions;
        return this;
    }

    /** Default: true */
    public EventBusBuilder logNoSubscriberMessages(boolean logNoSubscriberMessages) {
        this.logNoSubscriberMessages = logNoSubscriberMessages;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendSubscriberExceptionEvent(boolean sendSubscriberExceptionEvent) {
        this.sendSubscriberExceptionEvent = sendSubscriberExceptionEvent;
        return this;
    }

    /** Default: true */
    public EventBusBuilder sendNoSubscriberEvent(boolean sendNoSubscriberEvent) {
        this.sendNoSubscriberEvent = sendNoSubscriberEvent;
        return this;
    }

    /**
     * Fails if an subscriber throws an exception (default: false).
     * <p/>
     * Tip: Use this with BuildConfig.DEBUG to let the app crash in DEBUG mode (only). This way, you won't miss
     * exceptions during development.
     */
    public EventBusBuilder throwSubscriberException(boolean throwSubscriberException) {
        this.throwSubscriberException = throwSubscriberException;
        return this;
    }

    /**
     * By default, EventBus considers the event class hierarchy (subscribers to super classes will be notified).
     * Switching this feature off will improve posting of events. For simple event classes extending Object directly,
     * we measured a speed up of 20% for event posting. For more complex event hierarchies, the speed up should be
     * >20%.
     * <p/>
     * However, keep in mind that event posting usually consumes just a small proportion of CPU time inside an app,
     * unless it is posting at high rates, e.g. hundreds/thousands of events per second.
     */
    public EventBusBuilder eventInheritance(boolean eventInheritance) {
        this.eventInheritance = eventInheritance;
        return this;
    }


    /**
     * Provide a custom thread pool to EventBus used for async and background event delivery. This is an advanced
     * setting to that can break things: ensure the given ExecutorService won't get stuck to avoid undefined behavior.
     */
    public EventBusBuilder executorService(ExecutorService executorService) {
        this.executorService = executorService;
        return this;
    }

    /**
     * Method name verification is done for methods starting with onEvent to avoid typos; using this method you can
     * exclude subscriber classes from this check. Also disables checks for method modifiers (public, not static nor
     * abstract).
     */
    public EventBusBuilder skipMethodVerificationFor(Class<?> clazz) {
        if (skipMethodVerificationForClasses == null) {
            skipMethodVerificationForClasses = new ArrayList<>();
        }
        skipMethodVerificationForClasses.add(clazz);
        return this;
    }

    /** Forces the use of reflection even if there's a generated index (default: false). */
    public EventBusBuilder ignoreGeneratedIndex(boolean ignoreGeneratedIndex) {
        this.ignoreGeneratedIndex = ignoreGeneratedIndex;
        return this;
    }

    /** Enables strict method verification (default: false). */
    public EventBusBuilder strictMethodVerification(boolean strictMethodVerification) {
        this.strictMethodVerification = strictMethodVerification;
        return this;
    }

    /** Adds an index generated by EventBus' annotation preprocessor. */
    public EventBusBuilder addIndex(SubscriberInfoIndex index) {
        if(subscriberInfoIndexes == null) {
            subscriberInfoIndexes = new ArrayList<>();
        }
        subscriberInfoIndexes.add(index);
        return this;
    }

    /**
     * Installs the default EventBus returned by {@link EventBus#getDefault()} using this builders' values. Must be
     * done only once before the first usage of the default EventBus.
     *
     * @throws EventBusException if there's already a default EventBus instance in place
     */
    public EventBus installDefaultEventBus() {
        synchronized (EventBus.class) {
            if (EventBus.defaultInstance != null) {
                throw new EventBusException("Default instance already exists." +
                        " It may be only set once before it's used the first time to ensure consistent behavior.");
            }
            EventBus.defaultInstance = build();
            return EventBus.defaultInstance;
        }
    }

    /** Builds an EventBus based on the current configuration. */
    public EventBus build() {
        return new EventBus(this);
    }

}

這里,看上去代碼很多
大多數(shù)都是設置boolean值的方法
一個設置 線程池 ExecutorService的方法
一個 給List 添加 Class<?> 的 skipMethodVerificationFor方法
一個給List添加SubscriberInfoIndex類型對象的 addIndex 方法
另外有 初始化外面EventBus對象的 installDefaultEventBus() 和 build() 方法

總體溶其,就是設置boolean值骚腥,添加List對象的一個類


register(Object subscriber) 和 unregister(Object subscriber)

在外部使用的時候,我們最直接的瓶逃,除了getDefault()這個單例以外
就是 register 和 unregister了

register

public void register(Object subscriber) {
    Class<?> subscriberClass = subscriber.getClass();
    List<SubscriberMethod> subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
    synchronized (this) {
        for (SubscriberMethod subscriberMethod : subscriberMethods) {
            subscribe(subscriber, subscriberMethod);
        }
    }
}

代碼內(nèi)容束铭,也很好理解

  • 通過傳入的類(Activity中廓块,一般寫的是this,也就是Activity本身)
  • 得到對應的 Class<?> 對象契沫, 再通過 SubscriberMethodFinder對象(下一篇一起分析這個類)去得到 一個 SubscriberMethod的List
  • 把對應的List放入到一個容器中(應該用于之后通知的過程中带猴,判斷是否響應)

unregister

/** 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 {
        Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
    }
}

這里也比較好理解,通過容器懈万,拿到對應的Class<?> 的List
也就是某個Activity或者Fragment中拴清,對應的注解類型
循環(huán)去遍歷,最后在容器Map<Object, List<Class<?>>> typesBySubscriber 中
remove掉對應的key会通,也就是Activity或者Fragment中所有注解的方法


post方法

我們知道口予,對應的值,是通過post去完成的
這里 用 ThreadLocal的線程包裝類涕侈,去完成對應的線程記錄和操作
對應的泛型PostingThreadState對象沪停,記錄對應的信息,將對應的線程放入一個List中
通過對應的狀態(tài)驾凶,判斷Looper.getMainLooper() == Looper.myLooper() 是否是主線程等操作牙甫, 將狀態(tài)存入PostingThreadState的屬性中
最后掷酗,遍歷容器中的Event调违,
最后通過存儲的Subscription中的subscriberMethod的method,反射去invoke調用方法泻轰。


下一篇我們可以了解Eventbus3代碼分析(六):SubscriberMethodFinder類

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末技肩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子浮声,更是在濱河造成了極大的恐慌虚婿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泳挥,死亡現(xiàn)場離奇詭異然痊,居然都是意外死亡,警方通過查閱死者的電腦和手機屉符,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門剧浸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人矗钟,你說我怎么就攤上這事唆香。” “怎么了吨艇?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵躬它,是天一觀的道長。 經(jīng)常有香客問我东涡,道長冯吓,這世上最難降的妖魔是什么倘待? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮组贺,結果婚禮上延柠,老公的妹妹穿的比我還像新娘。我一直安慰自己锣披,他們只是感情好贞间,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雹仿,像睡著了一般增热。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胧辽,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天峻仇,我揣著相機與錄音,去河邊找鬼邑商。 笑死摄咆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的人断。 我是一名探鬼主播吭从,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼恶迈!你這毒婦竟也來了涩金?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤暇仲,失蹤者是張志新(化名)和其女友劉穎步做,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奈附,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡全度,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了斥滤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片将鸵。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖中跌,靈堂內(nèi)的尸體忽然破棺而出咨堤,到底是詐尸還是另有隱情,我是刑警寧澤漩符,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響凸克,放射性物質發(fā)生泄漏议蟆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一萎战、第九天 我趴在偏房一處隱蔽的房頂上張望咐容。 院中可真熱鬧,春花似錦蚂维、人聲如沸戳粒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔚约。三九已至,卻和暖如春涂籽,著一層夾襖步出監(jiān)牢的瞬間苹祟,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工评雌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留树枫,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓景东,卻偏偏與公主長得像砂轻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子耐薯,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容