概述
EventBus是一款針對Android優(yōu)化的發(fā)布/訂閱(publish/subscribe)事件總線抓半。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service狮惜,線程之間傳遞消息。簡化了應用程序內各組件間锻狗、組件與后臺線程間的通信祟同。優(yōu)點是開銷小,代碼更優(yōu)雅厢蒜。以及將發(fā)送者和接收者解耦霞势。比如請求網(wǎng)絡,等網(wǎng)絡返回時通過Handler或Broadcast通知UI斑鸦,兩個Fragment之間需要通過Listener通信愕贡,這些需求都可以通過EventBus實現(xiàn)。
EventBus作為一個消息總線巷屿,有三個主要的元素:
Event:事件固以。可以是任意類型的對象
Subscriber:事件訂閱者嘱巾,接收特定的事件憨琳。在EventBus中,使用約定來指定事件訂閱者以簡化使用旬昭。即所有事件訂閱都都是以onEvent開頭的函數(shù)篙螟,具體來說,函數(shù)的名字是onEvent问拘,onEventMainThread遍略,onEventBackgroundThread慢味,onEventAsync這四個,這個和 ThreadMode(下面講)有關墅冷。
Publisher:事件發(fā)布者纯路,用于通知 Subscriber 有事件發(fā)生∧蓿可以在任意線程任意位置發(fā)送事件驰唬,直接調用eventBus.post(Object) 方法,可以自己實例化 EventBus 對象腔彰,但一般使用默認的單例就好了:EventBus.getDefault()叫编, 根據(jù)post函數(shù)參數(shù)的類型,會自動調用訂閱相應類型事件的函數(shù)霹抛。
關于ThreadMode
前面說了搓逾,Subscriber的函數(shù)只能是那4個,因為每個事件訂閱函數(shù)都是和一個ThreadMode相關聯(lián)的杯拐,ThreadMode指定了會調用的函數(shù)霞篡。有以下四個ThreadMode:
PostThread:事件的處理在和事件的發(fā)送在相同的進程,所以事件處理時間不應太長端逼,不然影響事件的發(fā)送線程朗兵,而這個線程可能是UI線程。對應的函數(shù)名是onEvent顶滩。
MainThread: 事件的處理會在UI線程中執(zhí)行余掖。事件處理時間不能太長,這個不用說的礁鲁,長了會ANR的盐欺,對應的函數(shù)名是onEventMainThread。
BackgroundThread:事件的處理會在一個后臺線程中執(zhí)行仅醇,對應的函數(shù)名是onEventBackgroundThread冗美,雖然名字 是BackgroundThread,事件處理是在后臺線程着憨,但事件處理時間還是不應該太長墩衙,因為如果發(fā)送事件的線程是后臺線程务嫡,會直接執(zhí)行事件甲抖,如果當前線程是UI線程,事件會被加到一個隊列中心铃,由一個線程依次處理這些事件准谚,如果某個事件處理時間太長,會阻塞后面的事件的派發(fā)或處理去扣。
Async:事件處理會在單獨的線程中執(zhí)行柱衔,主要用于在后臺線程中執(zhí)行耗時操作樊破,每個事件會開啟一個線程(有線程池),但最好限制線程的數(shù)目唆铐。
根據(jù)事件訂閱都函數(shù)名稱的不同哲戚,會使用不同的ThreadMode,比如果在后臺線程加載了數(shù)據(jù)想在UI線程顯示艾岂,訂閱者只需把函數(shù)命名onEventMainThread顺少。
對相應的函數(shù)名,進一步解釋一下:
onEvent:如果使用onEvent作為訂閱函數(shù)王浴,那么該事件在哪個線程發(fā)布出來的脆炎,onEvent就會在這個線程中運行,也就是說發(fā)布事件和接收事件線程在同一個線程氓辣。使用這個方法時秒裕,在onEvent方法中不能執(zhí)行耗時操作,如果執(zhí)行耗時操作容易導致事件分發(fā)延遲钞啸。
onEventMainThread:如果使用onEventMainThread作為訂閱函數(shù)几蜻,那么不論事件是在哪個線程中發(fā)布出來的,onEventMainThread都會在UI線程中執(zhí)行体斩,接收事件就會在UI線程中運行入蛆,這個在Android中是非常有用的,因為在Android中只能在UI線程中跟新UI硕勿,所以在onEvnetMainThread方法中是不能執(zhí)行耗時操作的哨毁。
onEventBackground:如果使用onEventBackgrond作為訂閱函數(shù),那么如果事件是在UI線程中發(fā)布出來的源武,那么onEventBackground就會在子線程中運行扼褪,如果事件本來就是子線程中發(fā)布出來的,那么onEventBackground函數(shù)直接在該子線程中執(zhí)行粱栖。
onEventAsync:使用這個函數(shù)作為訂閱函數(shù)话浇,那么無論事件在哪個線程發(fā)布,都會創(chuàng)建新的子線程在執(zhí)行onEventAsync闹究。
基本用法
引入EventBus:
compile 'org.greenrobot:eventbus:3.0.0'
定義事件:
public class MessageEvent { /* Additional fields if needed */ }
注冊事件接收者:
eventBus.register(this);
發(fā)送事件:
eventBus.post(event)
接收消息并處理:
public void onEvent(MessageEvent event) {}
注銷事件接收:
eventBus.unregister(this);
最后幔崖,proguard 需要做一些額外處理:
#EventBus
-keepclassmembers class ** {
public void onEvent*(**);
void onEvent*(**);
}
實戰(zhàn)舉例
關于Activity之間的通信
第一步:自定義一個定義Event事件,用來封裝信息
例子如下:
public class UserEvent {
private String userName;
public UserEvent() {
}
public UserEvent(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
第二步:注冊訂閱者和定義處理方法
public class MainActivity extends Activity {
private Button btn, fragment_btn;
private TextView service_tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注冊訂閱者
EventBus.getDefault().register(this);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent(MainActivity.this,
SecondActivity.class);
startActivity(intent);
}
});
fragment_btn = (Button) findViewById(R.id.fragment_btn);
fragment_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,
FragmenTestActivity.class);
startActivity(intent);
}
});
service_tv = (TextView) findViewById(R.id.service_tv);
startService(new Intent(this, EventTestService.class));
}
//定義處理接收方法
@Subscribe
public void onEventMainThread(UserEvent event) {
btn.setText(event.getUserName());
service_tv.setText(event.getUserName());
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
第三步:發(fā)送事件
public class SecondActivity extends Activity {
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final UserEvent ue = new UserEvent();
ue.setUserName("非著名程序員");
EventBus.getDefault().post(ue);
finish();
}
});
}
}
fragment,service等之間的通信和activity之間的基本一樣渣淤,就不過多的貼代碼解釋了赏寇,感興趣的同學可以直接下載demo,里面有它們之間的通信价认。
使用EventBus應該注意以下幾點:
同一個onEvent函數(shù)不能被注冊兩次嗅定,所以不能在一個類中注冊同時還在父類中注冊。
消息的接收是根據(jù)參數(shù)中的類名來決定執(zhí)行哪一個接收處理方法的用踩。即:訂閱者的處理方法是根據(jù)訂閱事件的類型來確定訂閱函數(shù)的渠退。
每個事件可以有多個訂閱者忙迁。
當Post一個事件時,這個事件類的父類的事件也會被Post碎乃。
所有事件處理方法必需是public void類型的姊扔,并且只有一個參數(shù)表示EventType。
在這里我把demo分享出去梅誓,demo里包含了Activity之間的通信旱眯,fragment之間的通信和service與activity之間的通信。
小編有給大家準備安卓進階學習資料視頻证九,加群即可獲取
群號:4112676