目錄
-
Eventbus前言
在項目開發中,總會遇到組件和組件之間,組件和線程、service之間進行通信,比如activity和多個fragment通信。android 原生也提供了一下方法,我們經常用的,有廣播,handler,寫回調方法以及intent。這些都可以解決通信需求,但是這樣耦合度比較高,並且代碼量也比較大。今天介紹的eventbus可以很方便的解決這些問題。
-
EventBus簡介
首先容許我盜一張圖:
大致意思是說,eventbus能夠簡化組件間通信,代碼更簡單,有效分離了時間發送方和接收方,並且有很多應用集成了eventbus安全和性能應該有保障。但是eventbus也有一個不太便利的地方。如果事件種類比較多的情況。那麼觀察者需要註冊的函數就會變得很多。這樣就會帶來一些不便,再有就是後來者接手項目,不熟悉代碼的情況下,比較難找到他的來龍去脈。
最後單獨說一下他的基本原理: eventbus就是一個典型的觀察者模式的使用,通過publisher發佈消息,然後Subscriber接收消息。然後進行處理。整個結構大致有三個模塊需要注意:
- 1 event:發佈者發佈的消息,可以是繼承自Object的任意類。
- 2 publisher:事件的發佈者,可以在任意線程發佈消息,一般通過EventBus.getDefault().post(Event)就可以發佈。
- 3 Subscriber: 事件的接收者,通過register,unregister函數來註冊成爲觀察者。處理事件的方法要通過註解@Subscribe()中的參數來標明處理事件的線程模型,優先權,以及是否是黏性廣播。
在觀察者類中處理消息的函數要通過註解@Subscribe(ThreadMode,isSticky,priority)來指定處理消息的一些基本信息,註解共有三個參數。其中ThreadMode表示在哪個線程裏面處理收到的消息,它有四種方式:
- 1 POSTING, 默認參數,哪個線程發佈的消息,就在哪個線程裏面處理消息。
- 2 MAIN, 表示在主線程處理消息,就是ui線程,不能進行耗時操作。
- 3 BACKGROUND, 表示後臺線程處理,不能進行ui操作,如果發佈消息在ui線程中發佈,那會重啓一個線程,如果是後臺線程,就在發佈消息的線程處理。
- 4 ASYNC ,無論發佈線程是哪個,都會重新開一個線程處理。可以進行耗時操作。
sticky 這個參數表示是否是黏性廣播,默認false,非黏性廣播當發佈者發佈消息的時候,沒有註冊的開發者不能收到任何消息,如果註冊爲黏性,那麼當觀察者註冊成功之後,會收到最後一條發佈的廣播。
priority表示處理的優先級。默認爲0.
-
EventBus使用
首先添加依賴:
implementation 'org.greenrobot:eventbus:3.1.1'
如果需要混淆要添加一下代碼:
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
# Only required if you use AsyncExecutor
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
簡單寫一個消息類:
public class MessageEvent extends MessageObject{
String message;
int id;
public MessageEvent(String msg,int id){
super(msg);
this.message = msg;
this.id = id;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
eventbus可以用於activity,fragment,service等控件,其註冊方式都一樣,本文用activity做例子,發送消息的activity如下:
public class MainActivity extends Activity {
@BindView(R.id.mainclick)
Button mainClick;
@BindView(R.id.threadclick)
Button threadClick;
WidgetBroadcastReceiver mReceiver;
RxPermissions rxPermissions;
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
postMsgMain();
postMsgThread();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mReceiver = new WidgetBroadcastReceiver();
ButterKnife.bind(this);
mainClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent ii = new Intent(MainActivity.this, EventBusActivity.class);
startActivity(ii);
mHandler.sendEmptyMessageDelayed(1, 1000 * 5);
}
});
}
private void postMsgMain(){
EventBus.getDefault().post(new MessageObject("this is default"));
Log.e("tag"," ****main id===="+Thread.currentThread().getId());
}
private void postMsgThread() {
new Thread(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new MessageEvent("from thread",1 ));
Log.e("tag","*thread id===="+Thread.currentThread().getId());
}
}).start();
}
}
點擊按鈕延後5,6秒通過EventBus.getDefault().post()分別發送一個主線程消息和後臺消息。
public class EventBusActivity extends Activity {
@BindView(R.id.content_text)
TextView contentView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_bus);
ButterKnife.bind(this);
//註冊觀察者
EventBus.getDefault().register(this);
}
/**
* 處理消息,只能是一個參數,通過參數識別處理哪個消息。發送的消息和參數匹配纔會處理。
* @param me
*/
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageObject me) {
String content = me.getObject();
contentView.setText(content);
Log.e("tag", "the MAIN msg id==="+Thread.currentThread().getId());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEvent1(MessageEvent me) {
String content = me.getMessage();
Log.e("tag", "the POSTING msg===" + me.getMessage()+Thread.currentThread().getId());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEvent2(MessageEvent me) {
String content = me.getMessage();
Log.e("tag", "the BACKGROUND msg===" + me.getMessage()+Thread.currentThread().getId());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEvent3(MessageEvent me) {
String content = me.getMessage();
Log.e("tag", "the ASYNC msg===" + me.getMessage()+Thread.currentThread().getId());
}
@Override
protected void onDestroy() {
super.onDestroy();
if(EventBus.getDefault().isRegistered(this)) {
//取消註冊
EventBus.getDefault().unregister(this);
}
}
}
在這裏接收處理消息。在這個例子中通過打印線程id確認執行屬性。日誌如下:
EventBus的基本用法就是這樣,接下來我會分析源碼來解釋eventbus的運行機制。
EventBus的github地址: