Android EventBus框架入門
在Android開發中可能會遇到過這樣一種情況,兩個Activity或者Activity與Service、Activity與後臺執行緒、執行緒與執行緒之間需要頻繁的進行通訊,Android官方的解決方案有兩種,一種是使用Handle,一種是使用廣播,但是這兩種方式都不是很好用,這時候就輪到EventBus出場了!EventBus就以非常簡便的方式解決了這樣的問題~
這裡有一個我寫的小Demo,算是拋磚引玉吧。
EventBus它的思想其實和廣播差不多(什麼!不明白廣播?這可是四大元件之一!可以百度一下),就是傳送訊息和接收訊息,在EventBus中訊息稱為事件,同一時間傳送事件的可以不止一個,同一時間接收事件的也可以不是一個。關於EventBus的思想,還可以參考計算機硬體中的匯流排。
好了,我們來看看如何使用EventBus吧~
1、這第一步肯定是配置Gradle了
compile ‘org.greenrobot:eventbus:3.0.0’
2、事件類
我們使用EventBus傳遞事件的時候要傳遞一個物件,我們可以傳遞自定義類物件,也可以傳遞java型別物件,不過,由於它傳遞的是一個物件,所以如果要傳遞int型別的資料,要傳遞Integer!當然其他型別也是這樣(好多人都會問,我傳遞一個數字怎麼傳不過去啊)
這裡我自定義一個類吧~看程式碼:
package com.mql.www.eventbusdemo.events; /** * * Created by MQL on 2017/8/20. */ public class MessageEvent { private String message; public MessageEvent(String message) { this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
非常簡單的一個類,只有一個屬性,geter和seter方法以及構造方法。這樣這個自定義類就等著被使用吧~
2、註冊,接收事件
這裡先看看整體程式碼,程式碼下面進行解釋:
public class MainActivity extends AppCompatActivity { private TextView tv_meaasge; private Button btn_message; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); EventBus.getDefault().register(this);//註冊 tv_meaasge = (TextView)findViewById(R.id.main_tv); tv_meaasge.setText("MainActivity"); btn_message = (Button)findViewById(R.id.main_btn); btn_message.setText("跳轉到SecondActivity"); btn_message.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { startActivity(new Intent(MainActivity.this,SecondActivity.class)); } }); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this);//取消註冊 } //事件處理 @Subscribe(threadMode = ThreadMode.MAIN) public void onMoonEvent(MessageEvent messageEvent){ tv_meaasge.setText(messageEvent.getMessage()); } }
(1)先看看註冊吧,找出相關程式碼:
EventBus.getDefault().register(this);//註冊
就這樣一行程式碼,這個類或者說這個Activity就已經在EventBus上註冊成功了,那麼註冊有什麼作用呢,這就相當於告訴EventBus:以後只要有事件傳送,你就要通知我,無論在哪個執行緒,無論在哪個類裡面傳送的。
(2)再看看取消註冊,找出相關程式碼:
EventBus.getDefault().unregister(this);//取消註冊
這樣新增一行程式碼,這個類或者說這個Activity就取消了註冊,這就相當於告訴EventBus:以後的事件不需要通知我了。這一行程式碼無論寫在什麼地方都可以生效,一般來講當Activity銷燬時必須要取消註冊,所以我在onDestroy方法中取消了註冊。
看完註冊和取消註冊,他們倆都有一個共同的特點就是都有一個EventBus.getDefault(),這句程式碼會返回一個預設的EventBus物件,當然我們也一個自己構造一個EventBus物件,這要使用EventBusBuilder類,很顯然這是建造者模式(什麼?不知道建造者模式是啥?沒關係目前不需要知道),我們使用這個預設的EventBus物件已經能夠滿足日常需求了。
(3)事件處理,我們找出相關程式碼:
//事件處理
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMoonEvent(MessageEvent messageEvent){
tv_meaasge.setText(messageEvent.getMessage());
}
首先我們可以看到這裡有一個註解Subscribe(什麼!不明白註解是什麼?看看這篇文章吧),這標識了這個方法為一個EventBus事件處理方法,註解裡面還有一個引數,這個引數的含義是指定事件處理的執行緒,引數可取的值有四個:
POSTING(預設) //這是預設的引數,使用該引數時,事件處理的執行緒與事件發出的執行緒是同一個執行緒,也就是說,該方法接收的事件是從哪個執行緒
中發出的,該方法的處理執行緒就是哪個執行緒。
MAIN //事件處理執行緒是UI執行緒
BACKGROUND //這個引數就有點意思了,如果接收的事件是從UI執行緒發出的,則事件處理會在新執行緒中執行,如果接收的事件是從子執行緒發出的,則
事件處理執行緒和事件發出執行緒是同一個執行緒。
ASYNC //事件處理在新執行緒中執行。
其次,我們這個方法不需要在任何地方手動呼叫,這就是註解的強大作用啦,當有事件傳送時,EventBus會先去找這些被註解了的方法,然後進行事件型別匹配(如果現在不明白,先知道有這麼回事,看完下面的事件傳送就明白了),如果事件型別匹配上,EventBus就會自動呼叫這個方法~
最後,這個方法的名字可以隨意起,阿貓阿狗都可以~
3、事件傳送
我們還是先看下程式碼,下面解釋:
public class SecondActivity extends AppCompatActivity {
private TextView tv_second;
private Button btn_second;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
EventBus.getDefault().register(this);
tv_second = (TextView)findViewById(R.id.second_tv);
btn_second = (Button)findViewById(R.id.second_btn);
btn_second.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread() {
@Override
public void run() {
//傳送事件
EventBus.getDefault().post(new MessageEvent("我是SecondActivity傳過來的message"));
}
}.run();
}
});
}
}
我們來單獨看看傳送事件:
EventBus.getDefault().post(new MessageEvent("我是SecondActivity傳過來的message"));
還是先獲取了一個預設的EventBus物件,然後呼叫它的post方法,就這樣,SecondActivity就成功通知EventBus傳送了一條事件,可以看到我們是子執行緒中傳送的,不過我們的接收方法已經用註解標識了在UI執行緒中執行。我們可以看到本次事件傳送的事件型別是一個我們一開始定義好的MessageEvent類自定義型別,回過頭去發現我們接受方法的引數也是一個MessageEvent型別,這樣本次傳送的事件就能被剛剛的接收方法接收並處理,剛剛說的型別匹配也就是這個意思。
當然,如果我們傳送其他型別的事件,比如傳送一個String字串,就像這樣:
EventBus.getDefault().post("我是SecondActivity傳過來的message");
那麼我們剛剛的接收方法就無法接收到事件,因為事件型別不匹配。
對於一個傳送事件來說,接收事件可能不只是一個,只要型別匹配成功,都可以接收。
這樣,一個 傳送事件—接收事件 的過程也就解釋完了。
MQL於2017年8月20日完成本文。