天天看點

EventBus-再也不用什麼Handler了[轉]EventBus使用詳解(二)——EventBus使用進階

我在實際項目中使用EventBus經驗總結:

  剛開始聽到EventBus的時候,覺得好像比較高大上,沒有學過,不敢用。但是還是情不自禁的用到了項目當中。但是随着EventBus使用的地方越多,問題就出現了,就像見了鬼一樣。

  問題1

  》描述:比如在Activity裡有2個或多個Fragment,在兩個Fragment裡都會在子線程中釋出

     MessageEvent在UI線程裡吐司。但是問題來了,在FragmentA裡我會請求網絡,然後我又到了

     FragmentB中,竟然會接受到了FragmentA裡的消息事件。  

  》原因分析:既然在Fragment裡可以接受到FragmentA的消息,說明FragmentA沒有unRegist事件。

          原因是我照搬網上的代碼,在onCreate裡訂閱事件,在onDestroy裡unRegist事件。

        但實際上從FragmentA切換到FragmentB的時候,FragmentA是沒有走onDestroy方法的。

  》解析方案:于是我決定在onStart與onStop方法裡來走regist與unRegist方法。

        雖然這個問題解決了,但是新的問題又來了。FragmentA裡的吐司事件又接收不到了,

        原因是FragmentA裡的事件是在onActivityCreated方法裡執行的,而這個生命周期的方

        法又是在onStart之前執行的。是以當請求網絡回調釋出事件的時候,還沒有訂閱事件。

  于是乎,我做了一個雙重保險:

<code>@Override</code>

<code>public</code> <code>void</code> <code>onCreate(Bundle savedInstanceState) {</code>

<code>    </code><code>super</code><code>.onCreate(savedInstanceState);</code>

<code>    </code><code>EventBus.getDefault().register(</code><code>this</code><code>);</code>

<code>}</code>

<code>public</code> <code>void</code> <code>onStart() {</code>

<code>    </code><code>super</code><code>.onStart();</code>

<code>    </code><code>if</code><code>(!EventBus.getDefault().isRegistered(</code><code>this</code><code>)){</code>

<code>        </code><code>EventBus.getDefault().register(</code><code>this</code><code>);</code>

<code>    </code><code>}</code>

<code>public</code> <code>void</code> <code>onStop() {</code>

<code>    </code><code>super</code><code>.onStop();</code>

<code>    </code><code>EventBus.getDefault().unregister(</code><code>this</code><code>);</code>

<code>public</code> <code>void</code> <code>onDestroyView() {</code>

<code>    </code><code>super</code><code>.onDestroyView();</code>

<code>    </code><code>ButterKnife.reset(</code><code>this</code><code>);</code>

<code>    </code><code>if</code><code>(EventBus.getDefault().isRegistered(</code><code>this</code><code>)){</code>

<code>        </code><code>EventBus.getDefault().unregister(</code><code>this</code><code>);</code>

 問題2

 搞開發就是這樣,問題問題層出不窮。

 》描述:進入登入Fragment,沒有點選登入按鈕就退出了。竟然還解析了登入,并且登入的吐司竟然彈在了首頁上。

 》原因分析:最開始,打的bug竟然沒有走,後來又走了,才找到原因。事件定義重複了,首頁在

        onResume裡請求網絡會釋出一個事件,因為事件的int類型與登入Fragment裡訂閱的登入

         解析事件的int型相重複。但是即使是這樣,登入Fragment關閉了不可能接收到首頁的事

        件啊。主要原因還是因為登入Fragment的onDestroy方法有延遲,登入Fragment雖然不

        見了,但是觸發了首頁Fragment的onResume事件,登入Fragment沒有來得及取消訂閱就

       接受到了首頁Fragment的登入解析事件,然後又把吐司給首頁Fragment了。

 》解決方案:隻要将沖突的事件int類型值改一下就行了。

 綜上所述,EventBus訂閱與取消訂閱要及時準确(對所在類的生命周期把握準确),事件的定義(不同僚件一定要有唯一辨別),另外還有一點,事件類容易越寫越多,要注意重構抽取。

EventBus概論

  EventBus是Google Guava庫裡的一個類,用來進行消息傳遞,線程之間通訊。

2.EventBus的使用

  首先必須要入庫

  onCreate()  注冊EventBus    EventBus.register(Object ),注冊的對象決定釋出事件的參數

     所在方法的反射範圍,一般用this,表示掃描目前類中所有的方法。

  onDestroy()  登出EventBus   EventBus.unRegister(Object)

  釋出事件:EventBus.post(參數)   參數可以是任何類型,一般為實體類。

    一般在子線程中釋出獲得的資料,然後通過在主線程中的方法來接收參數,并更新UI。

3.EventBus的底層

  EventBus的底層是用反射、集合Map技術。具體請看源碼。

<a href="http://m.blog.csdn.net/blog/u013173289/43970023" target="_blank">http://m.blog.csdn.net/blog/u013173289/43970023</a>

      本文轉自屠夫章哥  51CTO部落格,原文連結:http://blog.51cto.com/4259297/1705632,如需轉載請自行聯系原作者