1. 程式人生 > >Android開發學習之路-EventBus使用

Android開發學習之路-EventBus使用

轉載自:

https://www.cnblogs.com/Fndroid/p/5910992.html

EventBus是一個通過釋出、訂閱事件實現元件間訊息傳遞的工具。

它存在的目的,就是為了優化元件之間傳遞訊息的過程。傳統元件之間傳遞訊息的方法有使用廣播,回撥等,而這些方法使用都比較複雜。

工作原理:

依賴:

1 dependencies {
2     compile 'org.greenrobot:eventbus:3.0.0'
3 }

注:EventBus是事件-訂閱模型,實際上事件就是訊息,訂閱就是接收,本文不會很嚴格區分,方便理解為主!

1. 從簡單的入手:充當Handler

既然能傳送訊息,那麼自然在同一個元件下也能進行訊息的傳送和接收,也就是Handler的職責。

先定義一個事件的物件:

複製程式碼

 1 public class MessageEvent {
 2     private String message;
 3 
 4     public MessageEvent(String message) {
 5         this.message = message;
 6     }
 7 
 8     public String getMessage() {
 9         return message;
10     }
11 
12     @Override
13     public String toString() {
14         return message;
15     }
16 }

複製程式碼

這個事件物件只需要是Object的子類,沒其他要求,訊息的內容可以隨意定,這裡用一個String表示事件的訊息,toString直接輸出事件的內容。

在需要接收訊息的元件中,進行EventBus的繫結,這裡由Activity充當訂閱者(Subscriber),也就是訊息接收者。

複製程式碼

 1 public class MainActivity extends AppCompatActivity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7     }
 8 
 9     @Override
10     protected void onStart() {
11         super.onStart();
12         EventBus.getDefault().register(this); // 將當前Activity繫結為訂閱者
13     }
14 
15     @Override
16     protected void onStop() {
17         EventBus.getDefault().unregister(this); // 解綁
18         super.onStop();
19     }
20 
21     // 宣告一個訂閱方法,用於接收事件
22     @Subscribe
23     public void onEvent(MessageEvent messageEvent) {
24         Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
25     }
26 
27 }

複製程式碼

通過EventBus.getDefault方法獲取到一個EventBus的一個單例,也就是每次呼叫這個方法得到的都是同一個EventBus物件。而不同的EventBus物件訊息不會互通。

接著需要在Activity的onStart方法中進行對EventBus物件的繫結,在onStop方法中進行解綁。同時,需要定義用於接收事件的方法,並加上@Subscribe註解表明該方法用於接收訂閱事件。

接著,我們需要傳送事件:

1 EventBus.getDefault().post(new MessageEvent("I m Fndroid"));

這裡獲取的預設的EventBus物件,通過post方法進行事件的傳送,log如下:

 

2. 元件間通訊:代替廣播、回撥等

EventBus的存在,並不是為了替代Handler,而是用來進行元件間的通訊。有了上面的知識,接下來就不難了。

我們都知道,只要是同一個EventBus物件繫結的元件(Subscriber),訊息是互通的,也就是我們可以在Service中向Activity傳送事件進行通訊。(其他元件類似)

定義一個IntentService,並且傳送一個事件,而Activity,和上面一樣。

複製程式碼

 1 public class MyIntentService extends IntentService {
 2 
 3     public MyIntentService() {
 4         super("MyIntentService");
 5     }
 6 
 7     @Override
 8     protected void onHandleIntent(Intent intent) {
 9         EventBus.getDefault().post(new MessageEvent("From service"));
10     }
11 
12 }

複製程式碼

在Activity中開啟服務:

1 startService(new Intent(this, MyIntentService.class));

Log:

元件間的通訊變得如此簡單了。

 

3. 進階:持久事件、執行緒模式、優先順序

① 持久事件(StickyEvent):對於呼叫post方法傳送的普通訊息,會在第一次被接收到的時候被消費掉,也就是我們在@Subscribe方法下處理完了,這個訊息就消失了。而EventBus則提供了另一種型別的訊息——StickyEvent,這個訊息,會被儲存在RAM中,直到下一個StickyEvent被髮送才會被替換。每個EventBus物件都能通過geStickyEvent方法獲取最近發出的持久事件。

我們對Activity稍作修改,在訂閱方法中,把當前的持久訊息打印出來:

複製程式碼

1     // 宣告一個訂閱方法,用於接收事件
2     @Subscribe
3     public void onEvent(MessageEvent messageEvent) {
4         Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
5         Log.d(TAG, "onEvent: Sticky Event = [" + EventBus.getDefault().getStickyEvent(MessageEvent.class) + "]");
6     }

複製程式碼

接著對Service也進行修改,令其傳送一個StickyEvent:

複製程式碼

1     @Override
2     protected void onHandleIntent(Intent intent) {
3         EventBus.getDefault().post(new MessageEvent("From service"));
4         EventBus.getDefault().postSticky(new MessageEvent("From service2"));
5         EventBus.getDefault().post(new MessageEvent("From service3"));
6     }

複製程式碼

這裡看到,在第二次傳送的時候,呼叫了postSticky方法傳送事件,這就表明了該事件是一個持久事件,除非有新的同類型(不同型別的事件可以共存)持久事件被髮送,否則會一直被儲存在記憶體中,我們任何時候都能獲取得到。

Log:

可以看到,在第三次接收到訊息的時候,將StickyEvent打印出來,依舊是"From service2"。

同樣的,如果我們想要移除此持久事件,可以呼叫EventBus的removeStickyEvent方法來實現,如果要移除所有型別的持久事件,可以呼叫removeAllStickyEvent方法。

② 執行緒模式

EventBus允許我們對訂閱者進行執行緒設定,預設情況下,訂閱是和事件傳送處於同一執行緒的,我們不妨把訂閱的執行緒id打印出來看一看。

修改Activity中的@Subscribe方法:

1     @Subscribe
2     public void onEvent(MessageEvent messageEvent) {
3         Log.d(TAG, "onEvent: Thread id = [" + Thread.currentThread().getId() + "]");
4         Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
5     }

修改Service,讓其傳送一次普通事件,並且輸出當前執行緒id:

1     @Override
2     protected void onHandleIntent(Intent intent) {
3         Log.d(TAG, "onHandleIntent: Thread id = [" + Thread.currentThread().getId() + "]");
4         EventBus.getDefault().post(new MessageEvent("From service"));
5     }

列印Log:

對於訂閱者,有以下四種執行緒模式:

  1. POSTING:預設模式,訂閱和事件傳送在同一執行緒下進行
  2. MAIN:訂閱在主執行緒下進行,可以直接修改UI
  3. BACKGROUND:如果事件傳送在主執行緒,則訂閱在子執行緒下進行,如果事件傳送在子執行緒,則訂閱也在該子執行緒中進行
  4. ASYNC:如果事件傳送在主執行緒,則訂閱在子執行緒下進行,如果事件傳送在子執行緒,則訂閱會在其他子執行緒中進行

設定訂閱者執行緒很簡單,只需要在註解中賦值即可,如:

1     @Subscribe(threadMode = ThreadMode.MAIN)

③ 優先順序

每個元件中可以有多個訂閱方法,而我們可以對它們設定不同的優先順序,設定的方法也很簡單:

1     @Subscribe(priority = 88)

預設的優先順序為0,更高優先順序的訂閱方法會更先收到事件,而每個訂閱方法都可以對事件進行終止,可以通過以下方法停止事件傳遞:

1    EventBus.getDefault().cancelEventDelivery(messageEvent);

④ 自定義EventBus物件

通過getDefault方法獲取的是一個EventBus預設的單例,而我們可以通過EventBus.Builder來構造一個自定義的EventBus物件。


 

明白了用法以後,我們分析原始碼也會更加簡單。