前言
最近項(xiàng)目中寓搬,有好些后臺 Service谴轮,就免不了 Activity 和 Service 的通信,也就有了不少 Broadcast恕沫,寫了不少重復(fù)代碼礼旅,就產(chǎn)生了使用 EventBus 的意思,而且現(xiàn)在更新到了 EventBus 3.0俐东,用法有了些許不同跌穗,不過相比之前更方便。
EventBus 有什么用
在項(xiàng)目開發(fā)中虏辫,肯定有不少各組件之間蚌吸、組件與后臺線程之間的通信,比如說子線程請求數(shù)據(jù)砌庄,然后通過 Handler 在主線程(也就是 UI 線程)更新UI羹唠,當(dāng)然這種情況如果可以我會使用 Retrofit + Rxjava 實(shí)現(xiàn),主要是 Fragment 和 Activity娄昆,F(xiàn)ragment 和 Fragment 之間的通信肉迫,特別是Fragment 嵌套比較深的布局,如果通過 Listener 回調(diào)傳遞事件稿黄,需要一層一層的往上傳遞,會造成代碼的高度耦合跌造,同時代碼量也會大大增加杆怕。
EventBus 的優(yōu)點(diǎn)
- EventBus 能夠簡化各組件間的通信,簡化了代碼
- 能夠有效的分離事件發(fā)送方和接收方壳贪,解耦了代碼
- 速度快陵珍,輕量
四步驟
1. 定義事件
public static class MessageEvent { /* Additional fields if needed */ }
2. 創(chuàng)建 subscribers,定義并注釋訂閱方法违施,同時指定一個 Thread mode
在 EventBus3.0 之前必須要定義以 onEvent 開頭互纯,特定的那幾個方法:onEvent,onEventMainThread磕蒲,onEventBackgroundThread留潦,onEventAsync,但是在 3.0 之后事件處理的方法名可以隨便取辣往,不過需要加上注解 @subscribe() 兔院,并指定線程類型,默認(rèn)是 POSTING站削。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(MessageEvent event) {/* Do something */};
3. 注冊和注銷 subscriber坊萝,F(xiàn)ragment 和 Activity 應(yīng)該根據(jù)生命周期注冊
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
4. 發(fā)布事件
EventBus.getDefault().post(new MessageEvent());
線程模型 ThreadMode
- ThreadMode.POSTING(默認(rèn)) 事件處理函數(shù)的線程和發(fā)布事件的線程在同一線程
- ThreadMode.MAIN 事件處理函數(shù)在主線程(UI線程),不能進(jìn)行耗時操作
- ThreadMode.MAIN_ORDERED 事件處理函數(shù)在順序處理的主線程,事件處理程序必須迅速返回十偶,以避免阻塞主線程
- ThreadMode.BACKGROUND 事件處理函數(shù)在后臺線程菩鲜,可以進(jìn)行耗時操作,但不能進(jìn)行UI操作
- ThreadMode.ASYNC 無論事件發(fā)布的線程是哪一個惦积,事件處理函數(shù)始終都會新建一個子線程運(yùn)行接校,不能進(jìn)行UI操作
實(shí)例
實(shí)現(xiàn)一個簡單實(shí)例,在 Activity 中啟動一個服務(wù)荣刑,在服務(wù)中馅笙,假設(shè)過去了 5s,返回給 Activity 一個消息厉亏,讓 Activity 在頁面中顯示出來
不使用EventBus董习,通過廣播實(shí)現(xiàn)
Activity
public class BroadcastActivity extends AppCompatActivity {
private TextView mTvMsg;
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case "TIMEOUT":
Log.i("ysan", "Current thread = " + Thread.currentThread().getName());
String hello = intent.getStringExtra("hello");
mTvMsg.setText(hello);
break;
}
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
mTvMsg = findViewById(R.id.tv_message);
Intent timeService = new Intent(this, BroadService.class);
startService(timeService);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter("TIMEOUT");
registerReceiver(mReceiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
}
Service
public class BroadService extends Service {
@Override
public void onCreate() {
super.onCreate();
new Thread(){
@Override
public void run() {
try {
Thread.sleep(5000);
Intent timeout = new Intent("TIMEOUT");
timeout.putExtra("hello", "hello Broadcast");
sendBroadcast(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}
通過EventBus實(shí)現(xiàn)
Message類
傳遞數(shù)據(jù)的 bean 類,包裝了用來傳輸?shù)臄?shù)據(jù)
public class Message {
private String msg;
public Message(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
Activity
public class EventBusActivity extends AppCompatActivity {
private TextView mTvMsg;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
mTvMsg = findViewById(R.id.tv_message);
Intent timeService = new Intent(this, EventbusService.class);
startService(timeService);
Intent newsService = new Intent(this, NewsService.class);
startService(newsService);
}
@Override
protected void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
protected void onStop() {
super.onStop();
if (EventBus.getDefault().isRegistered(this))
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(Message msg) {
String s = msg.getMsg();
Log.i("ysan", "線程 >>>" + Thread.currentThread().getName() + "爱只,收到消息" + s);
mTvMsg.setText(s);
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onNewsEvent(News news) {
String s = news.getInfo();
Log.i("ysan", "線程 >>>" + Thread.currentThread().getName() + "皿淋,收到消息" + s);
mTvMsg.setText(s);
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onNewsevent(News news) {
String s = news.getInfo();
Log.i("ysan", "線程 >>>" + Thread.currentThread().getName() + ",收到消息" + s);
}
}
Service
public class EventbusService extends Service {
@Override
public void onCreate() {
super.onCreate();
new Thread(){
@Override
public void run() {
try {
Thread.sleep(5000);
Message msg = new Message("hello EventBus");
EventBus.getDefault().post(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
}