安卓EventBus使用方法,eventbus舉例

三水方發表於2020-10-18

原帖: 跳轉

1、EventBus 簡介

EventBus是一種用於Android的事件釋出-訂閱匯流排,由GreenRobot開發,Gihub地址是:EventBus。它簡化了應用程式內各個元件之間進行通訊的複雜度,尤其是碎片之間進行通訊的問題,可以避免由於使用廣播通訊而帶來的諸多不便。

1.1 三個角色

  1. Event:事件,它可以是任意型別,EventBus會根據事件型別進行全域性的通知。
  2. Subscriber:事件訂閱者,在EventBus 3.0之前我們必須定義以onEvent開頭的那幾個方法,分別是onEventonEventMainThreadonEventBackgroundThreadonEventAsync,而在3.0之後事件處理的方法名可以隨意取,不過需要加上註解@subscribe,並且指定執行緒模型,預設是POSTING
  3. Publisher:事件的釋出者,可以在任意執行緒裡釋出事件。一般情況下,使用EventBus.getDefault()就可以得到一個EventBus物件,然後再呼叫post(Object)方法即可。

1.2 四種執行緒模型

EventBus3.0有四種執行緒模型,分別是:

  1. POSTING:預設,表示事件處理函式的執行緒跟釋出事件的執行緒在同一個執行緒。
  2. MAIN:表示事件處理函式的執行緒在主執行緒(UI)執行緒,因此在這裡不能進行耗時操作。
  3. BACKGROUND:表示事件處理函式的執行緒在後臺執行緒,因此不能進行UI操作。如果釋出事件的執行緒是主執行緒(UI執行緒),那麼事件處理函式將會開啟一個後臺執行緒,如果果釋出事件的執行緒是在後臺執行緒,那麼事件處理函式就使用該執行緒。
  4. ASYNC:表示無論事件釋出的執行緒是哪一個,事件處理函式始終會新建一個子執行緒執行,同樣不能進行UI操作。

2、EventBus 使用

2.1 引入依賴

在使用之前先要引入如下依賴:

implementation 'org.greenrobot:eventbus:3.1.1'

2.2 定義事件

然後,我們定義一個事件的封裝物件。在程式內部就使用該物件作為通訊的資訊:

public class MessageWrap {
<span class="token keyword">public</span> <span class="token keyword">final</span> <span class="token class-name">String</span> message<span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">MessageWrap</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token class-name">String</span> message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">MessageWrap</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token class-name">MessageWrap</span><span class="token punctuation">(</span><span class="token class-name">String</span> message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>message <span class="token operator">=</span> message<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

2.3 釋出事件

然後,我們定義一個Activity:

@Route(path = BaseConstants.LIBRARY_EVENT_BUS_ACTIVITY1)
public class EventBusActivity1 extends CommonActivity<ActivityEventBus1Binding> {
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">doCreateView</span><span class="token punctuation">(</span><span class="token class-name">Bundle</span> savedInstanceState<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 為按鈕新增新增單擊事件</span>
    <span class="token function">getBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>btnReg<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span>v <span class="token operator">-&gt;</span> <span class="token class-name">EventBus</span><span class="token punctuation">.</span><span class="token function">getDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token function">getBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>btnNav2<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span> v <span class="token operator">-&gt;</span>
            <span class="token class-name">ARouter</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
                    <span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token class-name">BaseConstants</span><span class="token punctuation">.</span>LIBRARY_EVENT_BUS_ACTIVITY2<span class="token punctuation">)</span>
                    <span class="token punctuation">.</span><span class="token function">navigation</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Override</span>
<span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">onDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onDestroy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">EventBus</span><span class="token punctuation">.</span><span class="token function">getDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">unregister</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@Subscribe</span><span class="token punctuation">(</span>threadMode <span class="token operator">=</span> <span class="token class-name">ThreadMode</span><span class="token punctuation">.</span>MAIN<span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">onGetMessage</span><span class="token punctuation">(</span><span class="token class-name">MessageWrap</span> message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">getBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>tvMessage<span class="token punctuation">.</span><span class="token function">setText</span><span class="token punctuation">(</span>message<span class="token punctuation">.</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

這裡我們當按下按鈕的時候向EventBus註冊監聽,然後按下另一個按鈕的時候跳轉到拎一個Activity,並在另一個Activity釋出我們輸入的事件。在上面的Activity中,我們會新增一個監聽的方法,即onGetMessage,這裡我們需要為其加入註解Subscribe並指定執行緒模型為主執行緒MAIN。最後,就是在Activity的onDestroy方法中取消註冊該Activity。

下面是另一個Activity的定義,在這個Activity中,我們當按下按鈕的時候從EditText中取出內容並進行釋出,然後我們退出到之前的Activity,以測試是否正確監聽到釋出的內容。

@Route(path = BaseConstants.LIBRARY_EVENT_BUS_ACTIVITY2)
public class EventBusActivity2 extends CommonActivity<ActivityEventBus2Binding> {
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">protected</span> <span class="token keyword">void</span> <span class="token function">doCreateView</span><span class="token punctuation">(</span><span class="token class-name">Bundle</span> savedInstanceState<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">getBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>btnPublish<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span>v <span class="token operator">-&gt;</span> <span class="token function">publishContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">private</span> <span class="token keyword">void</span> <span class="token function">publishContent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token class-name">String</span> msg <span class="token operator">=</span> <span class="token function">getBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>etMessage<span class="token punctuation">.</span><span class="token function">getText</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">EventBus</span><span class="token punctuation">.</span><span class="token function">getDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token class-name">MessageWrap</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">ToastUtils</span><span class="token punctuation">.</span><span class="token function">makeToast</span><span class="token punctuation">(</span><span class="token string">"Published : "</span> <span class="token operator">+</span> msg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

}

根據測試的結果,我們的確成功地接收到了傳送的資訊。

2.4 黏性事件

所謂的黏性事件,就是指傳送了該事件之後再訂閱者依然能夠接收到的事件。使用黏性事件的時候有兩個地方需要做些修改。一個是訂閱事件的地方,這裡我們在先開啟的Activity中註冊監聽黏性事件:

@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
public void onGetStickyEvent(MessageWrap message) {
    String txt = "Sticky event: " + message.message;
    getBinding().tvStickyMessage.setText(txt);
}

另一個是釋出事件的地方,這裡我們在新的開的Activity中釋出黏性事件。即呼叫EventBus的postSticky方法來發布事件:

private void publishStickyontent() {
    String msg = getBinding().etMessage.getText().toString();
    EventBus.getDefault().postSticky(MessageWrap.getInstance(msg));
    ToastUtils.makeToast("Published : " + msg);
}

按照上面的模式,我們先在第一個Activity中開啟第二個Activity,然後在第二個Activity中釋出黏性事件,並回到第一個Activity註冊EventBus。根據測試結果,當按下注冊按鈕的時候,會立即觸發上面的訂閱方法從而獲取到了黏性事件。

2.5 優先順序

Subscribe註解中總共有3個引數,上面我們用到了其中的兩個,這裡我們使用以下第三個引數,即priority。它用來指定訂閱方法的優先順序,是一個整數型別的值,預設是0,值越大表示優先順序越大。在某個事件被髮布出來的時候,優先順序較高的訂閱方法會首先接受到事件。

為了對優先順序進行測試,這裡我們需要對上面的程式碼進行一些修改。這裡,我們使用一個布林型別的變數來判斷是否應該取消事件的分發。我們在一個較高優先順序的方法中通過該布林值進行判斷,如果未true就停止該事件的繼續分發,從而通過低優先順序的訂閱方法無法獲取到事件來證明優先順序較高的訂閱方法率先獲取到了事件。

這裡有幾個地方需要注意

  1. 只有當兩個訂閱方法使用相同的ThreadMode引數的時候,它們的優先順序才會與priority指定的值一致;
  2. 只有當某個訂閱方法的ThreadMode引數為POSTING的時候,它才能停止該事件的繼續分發。

所以,根據以上的內容,我們需要對程式碼做如下的調整:

// 用來判斷是否需要停止事件的繼續分發
private boolean stopDelivery = false;

@Override
protected void doCreateView(Bundle savedInstanceState) {
// …

<span class="token function">getBinding</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>btnStop<span class="token punctuation">.</span><span class="token function">setOnClickListener</span><span class="token punctuation">(</span>v <span class="token operator">-&gt;</span> stopDelivery <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

}

@Subscribe(threadMode = ThreadMode.POSTING, priority = 0)
public void onGetMessage(MessageWrap message) {
getBinding().tvMessage.setText(message.message);
}

// 訂閱方法,需要與上面的方法的threadMode一致,並且優先順序略高
@Subscribe(threadMode = ThreadMode.POSTING, sticky = true, priority = 1)
public void onGetStickyEvent(MessageWrap message) {
String txt = "Sticky event: " + message.message;
getBinding().tvStickyMessage.setText(txt);
if (stopDelivery) {
// 終止事件的繼續分發
EventBus.getDefault().cancelEventDelivery(message);
}
}

即我們在之前的程式碼之上增加了一個按鈕,用來將stopDelivery的值置為true。該欄位隨後將會被用來判斷是否要終止事件的繼續分發,因為我們需要在程式碼中停止事件的繼續分發,所以,我們需要將上面的兩個訂閱方法的threadMode的值都置為ThreadMode.POSTING

按照,上面的測試方式,首先我們在當前的Activity註冊監聽,然後跳轉到另一個Activity,釋出事件並返回。第一次的時候,這裡的兩個訂閱方法都會被觸發。然後,我們按下停止分發的按鈕,並再次執行上面的邏輯,此時只有優先順序較高的方法獲取到了事件並將該事件終止。

總結

上面的內容是EventBus的基本使用方法,相關的原始碼參考:Github

獲取更多技術文章可以直接關注我的公眾號「Hello 開發者」,另外感興趣的可以加入技術 QQ 交流群:1018235573.

安卓EventBus使用方法,eventbus舉例
公眾號資訊

以上,感謝閱讀~

"小禮物走一走,來簡書關注我"
讚賞支援 還沒有人讚賞,支援一下
Hello_開發者 所有文章第一時間更新在公眾號「Hello 開發者」! 2020 再出發,一起學習,共同成長!
總資產80 (約5.94元) 共寫了17.0W字 獲得522個贊 共223個粉絲
關注

相關文章