EventBus這個開源框架出來已經(jīng)很久了,深的很多開發(fā)者青睞,由greenrobot組織貢獻(該組織還貢獻了greenDAO),是一個Android事件發(fā)布/訂閱輕量級框架,通過解耦發(fā)布者和訂閱者簡化Android事件傳遞,EventBus可以代替Android傳統(tǒng)的Intent,Handler,Broadcast或接口函數(shù),在Fragment,Activity,Service線程之間傳遞數(shù)據(jù),執(zhí)行方法。
其最大的特點就是:代碼簡潔,是一種發(fā)布訂閱設(shè)計模式(觀察者設(shè)計模式)。在沒有EventBus之前我們通常用廣播來實現(xiàn)監(jiān)聽,或者自定義接口函數(shù)回調(diào),但有的場景我們也可以直接用Intent攜帶簡單數(shù)據(jù),或者在線程之間通過Handler處理消息傳遞。但無論是廣播還是Handler機制遠遠不能滿足我們高效的開發(fā),廣播是四大組件之一,許多系統(tǒng)級的事件都是通過廣播來通知的,比如說網(wǎng)絡(luò)的變化、電量的變化,短信發(fā)送和接收的狀態(tài),但是廣播是相對消耗時間和資源的,Handler雖然簡單但高復(fù)發(fā)的內(nèi)存泄漏困擾很多初級開發(fā)者,那么EventBus會很好消除這些缺點,那么本節(jié)我們來了解一下他的使用方法,很簡單的哦,相信以后你也會愛上的。
EventBus3.0源碼地址:https://github.com/greenrobot/EventBus
EventBus重要方法和類:
Event 傳遞的事件對象
Subscriber? 事件的訂閱者
Publisher? 事件的發(fā)布者
ThreadMode 定義函數(shù)在何種線程中執(zhí)行
他們之間的關(guān)系如圖:
那么具體該怎么操作呢? 請往下看
1)在需要訂閱事件的地方注冊事件,可以是Activity或者Fragment中
EventBus.getDefault().register(this@MainActivity)
2)創(chuàng)建Event消息類 —定義事件模型
該類可以不繼承任何基類也不需要實現(xiàn)任何接口,
class MessageEvent(val progress: Int)
這里我用Kotlin寫的,所以大家看起來會有些不習(xí)慣,不過相信大家看起來不會有問題,因為android的api是不變得,只是kotlin寫法稍有改變,會java的同學(xué)學(xué)起Kotlin也會很容易,由于Google現(xiàn)在墻裂推薦Kotlin,作為Android開發(fā)者還是不能掉隊,所以大家有時間也多嘗試這門小眾語言,繼續(xù)我們的內(nèi)容,
3)產(chǎn)生事件、發(fā)送事件
EventBus.getDefault().post(MessageEvent(time))
在我們需要傳遞消息的地方將數(shù)據(jù)封裝到消息類Event中發(fā)送出去,這里我們就將數(shù)據(jù)發(fā)送出去了,我們怎么接受這條消息呢? 接著看
4)消費事件,處理消息
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMessage(event: MessageEvent) {
progress!!.progress = event.progress
}
@Subscribr()注解標(biāo)識我們的線程模型,這里我們要更新進度條的進度,所以制定消費事件的線程為主線程,在3.0之前,EventBus還沒有使用注解方式。消息處理的方法也只能限定于onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分別代表四種線程模型。而在3.0之后,消息處理的方法可以任意命名,這是個很大方便,但是需要添加一個注解@Subscribe,并且要指定線程模型(默認為PostThread),需要注意的是事件處理函數(shù)的訪問權(quán)限必須為public,否則會報異常。
這里我們更新UI中進度條進度,大家可以在此取出消息內(nèi)容執(zhí)行自己的邏輯。
當(dāng)然,我們要記得取消訂閱,跟廣播邏輯很相似。
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this@MainActivity)
}
回到上面話題線程模型處,我們來了解這幾個線程模型具體含義:
在EventBus的事件處理函數(shù)中需要指定線程模型,即指定事件處理函數(shù)運行所在的想線程。在上面我們已經(jīng)接觸到了EventBus的四種線程模型。那他們有什么區(qū)別呢?在EventBus中的觀察者通常有四種線程模型,分別是PostThread(默認)、MainThread、BackgroundThread與Async。
PostThread:如果使用事件處理函數(shù)指定了線程模型為PostThread,那么該事件在哪個線程發(fā)布出來的,事件處理函數(shù)就會在這個線程中運行,也就是說發(fā)布事件和接收事件在同一個線程。在線程模型為PostThread的事件處理函數(shù)中盡量避免執(zhí)行耗時操作,因為它會阻塞事件的傳遞,甚至有可能會引起ANR。
MainThread:如果使用事件處理函數(shù)指定了線程模型為MainThread,那么不論事件是在哪個線程中發(fā)布出來的,該事件處理函數(shù)都會在UI線程中執(zhí)行。該方法可以用來更新UI,但是不能處理耗時操作。
BackgroundThread:如果使用事件處理函數(shù)指定了線程模型為BackgroundThread,那么如果事件是在UI線程中發(fā)布出來的,那么該事件處理函數(shù)就會在新的線程中運行,如果事件本來就是子線程中發(fā)布出來的,那么該事件處理函數(shù)直接在發(fā)布事件的線程中執(zhí)行。在此事件處理函數(shù)中禁止進行UI更新操作。
Async:如果使用事件處理函數(shù)指定了線程模型為Async,那么無論事件在哪個線程發(fā)布,該事件處理函數(shù)都會在新建的子線程中執(zhí)行。同樣,此事件處理函數(shù)中禁止進行UI更新操作。
EventBus黏性事件:
EventBus除了普通事件也支持粘性事件,這個有點類似廣播分類中的粘性廣播。本身粘性廣播用的就比較少,為了方便理解成訂閱在發(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)
//粘性事件,在需要的時候注冊,接受最后一條消息
}
//EventBus.getDefault().register(this@MainActivity)
}
這里我們沒有在onCreate()中注冊EventBus,我們是收不到廣播的,其實這里我們可以另外添加一個按鈕,在按鈕點擊事件里面注冊EventBus,我們這里把注冊這一步放在發(fā)送事件的后面,也可以按照剛才說的那種方式把注冊步驟放到另外一個button點擊事件里面。
對于粘性廣播我們都比較清楚屬于常駐廣播,對于EventBus粘性事件也類似,我們?nèi)绻辉傩枰撜承允录覀兛梢砸瞥?/p>
EventBus.getDefault().removeStickyEvent(MessageEvent(time))
或者調(diào)用移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();
如果對粘性事件還不是很熟悉的同學(xué)可以再去看看廣播的內(nèi)容,也可以將廣播內(nèi)容跟EventBus做個總結(jié),設(shè)計思想及其相似,都是基于觀察者模式,只是粘性體現(xiàn)在能夠收到訂閱之前發(fā)送的消息。但是它只能收到最新的一次消息,比如說在未訂閱之前已經(jīng)發(fā)送了多條黏性消息了,然后再訂閱只能收到最近的一條消息。
看到這里,你是不是對EventBus已經(jīng)有了很好的了解,EventBus使用很簡單,但是確實給項目和開發(fā)者帶來很大的方便,有機會大家可以嘗試看看EventBus的源碼,從源碼角度更深層次了解EventBus的強大,本節(jié)就到這兒,我們下次再見!!!? 晚安