前言
網(wǎng)上有很多教程戴已,為什么還需要寫一次埋凯?
因?yàn)榫W(wǎng)上很多基于2.4的,鑒于3.0跟2.4差別還是很大辐董,另外教程有點(diǎn)亂悴品,所以重寫一篇,方便大家(百度沒收錄因?yàn)椴恢С謌ithub pager简烘,所以只方便谷歌的苔严。。孤澎。)也方便自己届氢。
What
EventBus是什么?
EventBus是一個(gè)Android端優(yōu)化的publish/subscribe消息總線覆旭,簡化了應(yīng)用程序內(nèi)各組件間退子、組件與后臺線程間的通信。比如請求網(wǎng)絡(luò)型将,等網(wǎng)絡(luò)返回時(shí)通過Handler或Broadcast通知UI寂祥,兩個(gè)Fragment之間需要通過Listener通信,這些需求都可以通過EventBus實(shí)現(xiàn)茶敏。
另外EventBus其實(shí)是一類框架的總稱壤靶,只不過由于greenrobot做的很優(yōu)秀缚俏,所以大家說起EventBus的時(shí)候一般指的是greenrobot的EventBus,greenrobot應(yīng)該不會陌生吧惊搏,GreenDAO就出自他們之手。
why
為什么要用EventBus忧换?
使用一款第三方庫的原因不外乎因?yàn)榈谌綆旆庋b的好恬惯,使用方便,運(yùn)行效率高亚茬。原本EventBus3.0的效率就比EventBus2.4酪耳、Otto的效率高,配合eventbus-annotation-processor的話更是在原來EventBus3.0的基礎(chǔ)上效率高上一倍刹缝。
另外碗暗,假設(shè)我們的app需要在啟動時(shí)進(jìn)行網(wǎng)絡(luò)請求,可是網(wǎng)絡(luò)有延時(shí)梢夯,頁面加載完成之后再更新UI的話會造成頁面閃動言疗,用戶體驗(yàn)十分不好,所以我們一般會加一個(gè)啟動頁面颂砸,在這時(shí)候進(jìn)行數(shù)據(jù)加載噪奄、網(wǎng)絡(luò)請求等死姚。當(dāng)請求結(jié)束,得到數(shù)據(jù)之后跳轉(zhuǎn)到主頁面了勤篮,我們怎么把數(shù)據(jù)傳遞過去都毒?Sticky Broadcast確實(shí)可以不過重量級了。所以我們需要有一個(gè)輕量級的解決方案碰缔。EventyBus就是這么一個(gè)輕量級的框架账劲!
How
EventBus怎么用
添加依賴
dependencies {
......
compile 'org.greenrobot:eventbus:3.0.0'
provided 'de.greenrobot:eventbus-annotation-processor:3.0.0-beta1'
}
當(dāng)然也可以直接在AS里查找,只需要輸入EventBus就可以找到了金抡。
注冊
當(dāng)我們想使用EventBus去接收消息或者說訂閱消息之前涤垫,我們必須對其進(jìn)行注冊。通常寫在onCreate里:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
......
}
注銷
事物都是兩面的竟终,有注冊就會有注銷蝠猬,注銷寫在onDestroy里:
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
......
}
發(fā)布
假設(shè)我們在網(wǎng)絡(luò)通訊中獲取到了數(shù)據(jù),由于是異步處理统捶,所以不能直接return榆芦,我們需要通過一個(gè)媒介把消息傳遞出去,EventBus開過來了喘鸟。使用非常簡單匆绣,只需要在想要發(fā)布消息的地方加上那么一句話:
EventBus.getDefault().post(new ListItemBus(list));
其中消息一般為我們自己建的bean,如:
public class ListItemBus {
private List<FoodItem> foodListItems;
public ListItemBus(List<FoodItem> foodListItems) {
this.foodListItems = foodListItems;
}
public List<FoodItem> getFoodListItems() {
return foodListItems;
}
public void setFoodListItems(List<FoodItem> foodListItems) {
this.foodListItems = foodListItems;
}
}
訂閱
訂閱也十分方便什黑,在已注冊的activity或者fragment中崎淳,新建方法如下(方法名可以隨便取):
@Subscribe(threadMode = ThreadMode.MAIN)
public void ListEvent(ListItemBus listItemBus) {
......
}
EventBus是根據(jù)消息類來區(qū)分訂閱者的愕把,所以想不同的訂閱者接收不同的消息需要不同的消息類拣凹,如上面的ListItemBus,我們可以把他改成String恨豁,當(dāng)然發(fā)布放那邊傳的也要是String才行嚣镜。
@Subscribe注解
在Subscribe注解中,我們可以定義接收到消息之后的運(yùn)行方式橘蜜,優(yōu)先級等菊匿。
threadMode
定義執(zhí)行線程,提供了4個(gè)方法:
- MAIN : 在UI線程中運(yùn)行可以用于修改UI
- BACKGROUND :若當(dāng)前線程非UI線程則在當(dāng)前線程中執(zhí)行计福,否則加入后臺任務(wù)隊(duì)列跌捆,使用線程池調(diào)用
- ASYNC :加入后臺任務(wù)隊(duì)列,使用線程池調(diào)用象颖,一般用于網(wǎng)絡(luò)請求
- POSTING :默認(rèn)模式佩厚,會在發(fā)布的線程執(zhí)行
priority
定義優(yōu)先級,默認(rèn)為0力麸,數(shù)值越大可款,優(yōu)先級越高:
@Subscribe(threadMode = ThreadMode.MAIN,priority = 1)
public void ListEvent(ListItemBus listItemBus) {
......
}
sticky
文章開頭的時(shí)候我說過育韩,在啟動頁加載數(shù)據(jù)然后傳遞過去,可是假設(shè)啟動畫面需要持續(xù)3秒闺鲸,而我數(shù)據(jù)1秒加載完了筋讨,這時(shí)候傳遞過去,由于訂閱者還沒有初始化摸恍,所以接收不到消息悉罕,這時(shí)候我們就需要使用到sticky了。使用方法同樣很簡單立镶,只需要在想發(fā)布的地方把post換成postSticky:
EventBus.getDefault().postSticky(new ListItemBus(list));
訂閱者那端也很方便壁袄,在@Subscribe注解中加入sticky = true
即可。
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void ListEvent(ListItemBus listItemBus) {
......
}
后記
我Boss說過一句話媚媒,我們不單要會用嗜逻,還要知道他為什么這樣用,這時(shí)候缭召,我們就需要涉及源碼了栈顷,我看到一篇挺好的EventBus3.0源碼解析,大家可以看一下EventBus 3.0進(jìn)階:源碼及其設(shè)計(jì)模式 完全解析嵌巷。