EventBus 3.0使用詳解
01 前言
當我們進行專案開發的時候,往往是需要應用程式的各元件、元件與後臺執行緒間進行通訊,比如在子執行緒中進行請求資料,當資料請求完畢後通過Handler或者是廣播通知UI,而兩個Fragment之家可以通過Listener進行通訊等等。當我們的專案越來越複雜,使用Intent、Handler、Broadcast進行模組間通訊、模組與後臺執行緒進行通訊時,程式碼量大,而且高度耦合。現在就讓我們來學習一下EventBus 3.0吧。
02 什麼是EventBus
- simplifies the communication between components
decouples event senders and receivers
performs well with Activities, Fragments, and background threads
avoids complex and error-prone dependencies and life cycle issues- makes your code simpler
- is fast
- is tiny (~50k jar)
- is proven in practice by apps with 100,000,000+ installs
- has advanced features like delivery threads, subscriber priorities, etc.
大概的意思就是:EventBus能夠簡化各元件間的通訊,讓我們的程式碼書寫變得簡單,能有效的分離事件傳送方和接收方(也就是解耦的意思),能避免複雜和容易出錯的依賴性和生命週期問題。
03 關於EventBus的概述
三要素
- Event 事件。它可以是任意型別。
- Subscriber 事件訂閱者。在EventBus3.0之前我們必須定義以onEvent開頭的那幾個方法,分別是onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,而在3.0之後事件處理的方法名可以隨意取,不過需要加上註解@subscribe(),並且指定執行緒模型,預設是POSTING。
- Publisher 事件的釋出者。我們可以在任意執行緒裡釋出事件,一般情況下,使用EventBus.getDefault()就可以得到一個EventBus物件,然後再呼叫post(Object)方法即可。
四種執行緒模型
EventBus3.0有四種執行緒模型,分別是:
- POSTING (預設) 表示事件處理函式的執行緒跟釋出事件的執行緒在同一個執行緒。
- MAIN 表示事件處理函式的執行緒在主執行緒(UI)執行緒,因此在這裡不能進行耗時操作。
- BACKGROUND 表示事件處理函式的執行緒在後臺執行緒,因此不能進行UI操作。如果釋出事件的執行緒是主執行緒(UI執行緒),那麼事件處理函式將會開啟一個後臺執行緒,如果果釋出事件的執行緒是在後臺執行緒,那麼事件處理函式就使用該執行緒。
- ASYNC 表示無論事件釋出的執行緒是哪一個,事件處理函式始終會新建一個子執行緒執行,同樣不能進行UI操作。
04 EventBus的基本用法
舉個例子,我需要在一個Activity裡註冊EventBus事件,然後定義接收方法,這跟Android裡的廣播機制很像,你需要首先註冊廣播,然後需要編寫內部類,實現接收廣播,然後操作UI。所以,在EventBus中,你同樣得這麼做。
自定義一個事件類
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;
}
}
這裡有些同學,會有一些疑問,為什麼要建立這樣一個類,有什麼用途。其實這個類就是一個Bean類,裡面定義用來傳輸的資料的型別。
註冊事件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.getDefault().register(this);
}
當我們需要在Activity或者Fragment裡訂閱事件時,我們需要註冊EventBus。我們一般選擇在Activity的onCreate()方法裡去註冊EventBus,在onDestory()方法裡,去解除註冊。
解除註冊
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
傳送事件
EventBus.getDefault().post(messageEvent);
處理事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void XXX(MessageEvent messageEvent) {
...
}
前面我們說過,處理訊息的方法名字可以隨便取。但是需要加一個註解@Subscribe,並且要指定執行緒模型。
05 EventBus使用實戰
以上我們講了EventBus的基本用法,沒有用過的同學也不要擔心不會用,小編在這裡舉個小栗子。
第一步:新增依賴
compile 'org.greenrobot:eventbus:3.0.0'
第二步:定義訊息事件類
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;
}
}
第三步:註冊和解除註冊
分別在FirstActivity的onCreate()方法和onDestory()方法裡,進行註冊EventBus和解除註冊。
package com.example.lenovo.testapp.ui;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.lenovo.testapp.R;
import com.example.lenovo.testapp.event.MessageEvent;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
/**
* Created by ZZG on 2018/1/10.
*/
public class FirstActivity extends AppCompatActivity {
private Button mButton;
private TextView mText;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity);
mButton = (Button) findViewById(R.id.btn1);
mText = (TextView) findViewById(R.id.tv1);
mText.setText("今天是星期三");
EventBus.getDefault().register(this);
jumpActivity();
}
private void jumpActivity() {
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
});
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void Event(MessageEvent messageEvent) {
mText.setText(messageEvent.getMessage());
}
@Override
protected void onDestroy() {
super.onDestroy();
if(EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
}
}
事件處理
在這裡,事件的處理執行緒在主執行緒,是因為,我要讓TextView去顯示值。
在 SecondActivity裡去進行事件的傳送。
package com.example.lenovo.tezs;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import org.greenrobot.eventbus.EventBus;
/**
* Created by ZZG on 2018/1/10.
*/
public class SecondActivity extends AppCompatActivity {
private Button mButton2;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activity);
mButton2=(Button) findViewById(R.id.btn2);
jumpActivity();
}
private void jumpActivity() {
mButton2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
EventBus.getDefault().post(new MessageEvent("歡迎大家瀏覽我寫的部落格"));
finish();
}
});
}
}
很簡單,當點選按鈕的時候,傳送了一個事件。
執行程式。
1.PNG
在FirstActivity中,左邊是一個按鈕,點選之後可以跳轉到SecondActivity,在按鈕的右邊是一個TextView,用來進行結果的驗證。
2.PNG
這是SecondActivity,在頁面的左上角,是一個按鈕,當點選按鈕,就會發送了一個事件,最後這個Activity就會銷燬掉。
3.PNG
此時我們可以看到,FirstActivity裡的文字已經變成了,我們在SecondActivity裡設定的文字。
總結
經過這個簡單的例子,我們發現EventBus使用起來是如此的方便,當我們的程式碼量變得很多的時候,使用EventBus後你的邏輯非常的清晰,並且程式碼之間高度解耦,在進行元件、頁面間通訊的時候,EventBus是一個不錯的選擇。
Android技術討論Q群:947460837
作者:唱著歌的貓
連結:https://www.jianshu.com/p/f9ae5691e1bb
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。