EventBus這個(gè)開源框架出來已經(jīng)很久了眶拉,深的很多開發(fā)者青睞禀酱,由greenrobot組織貢獻(xiàn)(該組織還貢獻(xiàn)了greenDAO)矛洞,是一個(gè)Android事件發(fā)布/訂閱輕量級(jí)框架,通過解耦發(fā)布者和訂閱者簡(jiǎn)化Android事件傳遞为流,EventBus可以代替Android傳統(tǒng)的Intent,Handler,Broadcast或接口函數(shù),在Fragment,Activity,Service線程之間傳遞數(shù)據(jù)航攒,執(zhí)行方法磺陡。
其最大的特點(diǎn)就是:代碼簡(jiǎn)潔,是一種發(fā)布訂閱設(shè)計(jì)模式(觀察者設(shè)計(jì)模式)漠畜。在沒有EventBus之前我們通常用廣播來實(shí)現(xiàn)監(jiān)聽币他,或者自定義接口函數(shù)回調(diào),但有的場(chǎng)景我們也可以直接用Intent攜帶簡(jiǎn)單數(shù)據(jù)憔狞,或者在線程之間通過Handler處理消息傳遞蝴悉。但無論是廣播還是Handler機(jī)制遠(yuǎn)遠(yuǎn)不能滿足我們高效的開發(fā),廣播是四大組件之一瘾敢,許多系統(tǒng)級(jí)的事件都是通過廣播來通知的拍冠,比如說網(wǎng)絡(luò)的變化、電量的變化簇抵,短信發(fā)送和接收的狀態(tài)庆杜,但是廣播是相對(duì)消耗時(shí)間和資源的,Handler雖然簡(jiǎn)單但高復(fù)發(fā)的內(nèi)存泄漏困擾很多初級(jí)開發(fā)者碟摆,那么EventBus會(huì)很好消除這些缺點(diǎn)晃财,那么本節(jié)我們來了解一下他的使用方法,很簡(jiǎn)單的哦焦履,相信以后你也會(huì)愛上的拓劝。
EventBus3.0源碼地址:https://github.com/greenrobot/EventBus
EventBus重要方法和類:
Event 傳遞的事件對(duì)象
Subscriber? 事件的訂閱者
Publisher? 事件的發(fā)布者
ThreadMode 定義函數(shù)在何種線程中執(zhí)行
他們之間的關(guān)系如圖:
那么具體該怎么操作呢? 請(qǐng)往下看
1)在需要訂閱事件的地方注冊(cè)事件嘉裤,可以是Activity或者Fragment中
EventBus.getDefault().register(this@MainActivity)
2)創(chuàng)建Event消息類 —定義事件模型
該類可以不繼承任何基類也不需要實(shí)現(xiàn)任何接口郑临,
class MessageEvent(val progress: Int)
這里我用Kotlin寫的,所以大家看起來會(huì)有些不習(xí)慣屑宠,不過相信大家看起來不會(huì)有問題厢洞,因?yàn)閍ndroid的api是不變得,只是kotlin寫法稍有改變,會(huì)java的同學(xué)學(xué)起Kotlin也會(huì)很容易,由于Google現(xiàn)在墻裂推薦Kotlin躺翻,作為Android開發(fā)者還是不能掉隊(duì)丧叽,所以大家有時(shí)間也多嘗試這門小眾語言,繼續(xù)我們的內(nèi)容公你,
3)產(chǎn)生事件踊淳、發(fā)送事件
EventBus.getDefault().post(MessageEvent(time))
在我們需要傳遞消息的地方將數(shù)據(jù)封裝到消息類Event中發(fā)送出去,這里我們就將數(shù)據(jù)發(fā)送出去了陕靠,我們?cè)趺唇邮苓@條消息呢迂尝? 接著看
4)消費(fèi)事件,處理消息
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMessage(event: MessageEvent) {
progress!!.progress = event.progress
}
@Subscribr()注解標(biāo)識(shí)我們的線程模型剪芥,這里我們要更新進(jìn)度條的進(jìn)度垄开,所以制定消費(fèi)事件的線程為主線程,在3.0之前税肪,EventBus還沒有使用注解方式溉躲。消息處理的方法也只能限定于onEvent、onEventMainThread益兄、onEventBackgroundThread和onEventAsync锻梳,分別代表四種線程模型。而在3.0之后净捅,消息處理的方法可以任意命名唱蒸,這是個(gè)很大方便,但是需要添加一個(gè)注解@Subscribe灸叼,并且要指定線程模型(默認(rèn)為PostThread),需要注意的是事件處理函數(shù)的訪問權(quán)限必須為public庆捺,否則會(huì)報(bào)異常古今。
這里我們更新UI中進(jìn)度條進(jìn)度,大家可以在此取出消息內(nèi)容執(zhí)行自己的邏輯滔以。
當(dāng)然捉腥,我們要記得取消訂閱,跟廣播邏輯很相似你画。
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this@MainActivity)
}
回到上面話題線程模型處抵碟,我們來了解這幾個(gè)線程模型具體含義:
在EventBus的事件處理函數(shù)中需要指定線程模型,即指定事件處理函數(shù)運(yùn)行所在的想線程坏匪。在上面我們已經(jīng)接觸到了EventBus的四種線程模型拟逮。那他們有什么區(qū)別呢?在EventBus中的觀察者通常有四種線程模型适滓,分別是PostThread(默認(rèn))敦迄、MainThread、BackgroundThread與Async。
PostThread:如果使用事件處理函數(shù)指定了線程模型為PostThread罚屋,那么該事件在哪個(gè)線程發(fā)布出來的苦囱,事件處理函數(shù)就會(huì)在這個(gè)線程中運(yùn)行,也就是說發(fā)布事件和接收事件在同一個(gè)線程脾猛。在線程模型為PostThread的事件處理函數(shù)中盡量避免執(zhí)行耗時(shí)操作撕彤,因?yàn)樗鼤?huì)阻塞事件的傳遞,甚至有可能會(huì)引起ANR猛拴。
MainThread:如果使用事件處理函數(shù)指定了線程模型為MainThread羹铅,那么不論事件是在哪個(gè)線程中發(fā)布出來的,該事件處理函數(shù)都會(huì)在UI線程中執(zhí)行漆弄。該方法可以用來更新UI睦裳,但是不能處理耗時(shí)操作。
BackgroundThread:如果使用事件處理函數(shù)指定了線程模型為BackgroundThread撼唾,那么如果事件是在UI線程中發(fā)布出來的廉邑,那么該事件處理函數(shù)就會(huì)在新的線程中運(yùn)行,如果事件本來就是子線程中發(fā)布出來的倒谷,那么該事件處理函數(shù)直接在發(fā)布事件的線程中執(zhí)行蛛蒙。在此事件處理函數(shù)中禁止進(jìn)行UI更新操作。
Async:如果使用事件處理函數(shù)指定了線程模型為Async渤愁,那么無論事件在哪個(gè)線程發(fā)布牵祟,該事件處理函數(shù)都會(huì)在新建的子線程中執(zhí)行。同樣抖格,此事件處理函數(shù)中禁止進(jìn)行UI更新操作诺苹。
EventBus黏性事件:
EventBus除了普通事件也支持粘性事件,這個(gè)有點(diǎn)類似廣播分類中的粘性廣播雹拄。本身粘性廣播用的就比較少收奔,為了方便理解成訂閱在發(fā)布事件之后,但同樣可以收到事件滓玖。訂閱/解除訂閱和普通事件一樣坪哄,但是處理訂閱函數(shù)有所不同,需要注解中添加sticky
= true势篡,
findViewById(R.id.button).setOnClickListener {
Thread(Runnable {
time = 0
while (time <= 100) {
EventBus.getDefault().postSticky(MessageEvent(time))
SystemClock.sleep(500)
time += 10
} }).start()
EventBus.getDefault().register(this@MainActivity)
//粘性事件翩肌,在需要的時(shí)候注冊(cè),接受最后一條消息
}
//EventBus.getDefault().register(this@MainActivity)
}
這里我們沒有在onCreate()中注冊(cè)EventBus,我們是收不到廣播的禁悠,其實(shí)這里我們可以另外添加一個(gè)按鈕念祭,在按鈕點(diǎn)擊事件里面注冊(cè)EventBus,我們這里把注冊(cè)這一步放在發(fā)送事件的后面绷蹲,也可以按照剛才說的那種方式把注冊(cè)步驟放到另外一個(gè)button點(diǎn)擊事件里面棒卷。
對(duì)于粘性廣播我們都比較清楚屬于常駐廣播顾孽,對(duì)于EventBus粘性事件也類似,我們?nèi)绻辉傩枰撜承允录覀兛梢砸瞥?/p>
EventBus.getDefault().removeStickyEvent(MessageEvent(time))
或者調(diào)用移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();
如果對(duì)粘性事件還不是很熟悉的同學(xué)可以再去看看廣播的內(nèi)容比规,也可以將廣播內(nèi)容跟EventBus做個(gè)總結(jié)若厚,設(shè)計(jì)思想及其相似,都是基于觀察者模式蜒什,只是粘性體現(xiàn)在能夠收到訂閱之前發(fā)送的消息测秸。但是它只能收到最新的一次消息,比如說在未訂閱之前已經(jīng)發(fā)送了多條黏性消息了灾常,然后再訂閱只能收到最近的一條消息霎冯。
看到這里,你是不是對(duì)EventBus已經(jīng)有了很好的了解钞瀑,EventBus使用很簡(jiǎn)單沈撞,但是確實(shí)給項(xiàng)目和開發(fā)者帶來很大的方便,有機(jī)會(huì)大家可以嘗試看看EventBus的源碼雕什,從源碼角度更深層次了解EventBus的強(qiáng)大缠俺,本節(jié)就到這兒,我們下次再見4丁R际俊!? 晚安