EventBus這個開源框架出來已經好久了,深的不少開發者青睞,由greenrobot 組織貢獻(該組織還貢獻了greenDAO),是一個Android事件發佈/訂閱輕量級框架,經過解耦發佈者和訂閱者簡化Android事件傳遞,EventBus能夠代替Android傳統的Intent,Handler,Broadcast或接口函數,在Fragment,Activity,Service線程之間傳遞數據,執行方法。
java
其最大的特色就是:代碼簡潔,是一種發佈訂閱設計模式(觀察者設計模式)。在沒有EventBus以前咱們一般用廣播來實現監聽,或者自定義接口函數回調,但有的場景咱們也能夠直接用Intent攜帶簡單數據,或者在線程之間經過Handler處理消息傳遞。但不管是廣播仍是Handler機制遠遠不能知足咱們高效的開發,廣播是四大組件之一,許多系統級的事件都是經過廣播來通知的,好比說網絡的變化、電量的變化,短信發送和接收的狀態,可是廣播是相對消耗時間和資源的,Handler雖然簡單但高復發的內存泄漏困擾不少初級開發者,那麼EventBus會很好消除這些缺點,那麼本節咱們來了解一下他的使用方法,很簡單的哦,相信之後你也會愛上的。android
EventBus3.0源碼地址:github.com/greenrobot/…git
EventBus重要方法和類:github
他們之間的關係如圖:
設計模式
那麼具體該怎麼操做呢? 請往下看api
EventBus.getDefault().register(this@MainActivity)
複製代碼
該類能夠不繼承任何基類也不須要實現任何接口,bash
class MessageEvent(val progress: Int)複製代碼
這裏我用Kotlin寫的,因此你們看起來會有些不習慣,不過相信你們看起來不會有問題,由於android的api是不變得,只是kotlin寫法稍有改變,會java的同窗學起Kotlin也會很容易,因爲Google如今牆裂推薦Kotlin,做爲Android開發者仍是不能掉隊,因此你們有時間也多嘗試這門小衆語言,繼續咱們的內容,網絡
EventBus.getDefault().post(MessageEvent(time))
複製代碼
在咱們須要傳遞消息的地方將數據封裝到消息類Event中發送出去,這裏咱們就將數據發送出去了,咱們怎麼接受這條消息呢? 接着看框架
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEventMessage(event: MessageEvent) {
progress!!.progress = event.progress
}複製代碼
@Subscribr()註解標識咱們的線程模型,這裏咱們要更新進度條的進度,因此制定消費事件的線程爲主線程,在3.0以前,EventBus尚未使用註解方式。消息處理的方法也只能限定於onEvent、onEventMainThread、onEventBackgroundThread和onEventAsync,分別表明四種線程模型。而在3.0以後,消息處理的方法能夠任意命名,這是個很大方便,可是須要添加一個註解@Subscribe,而且要指定線程模型(默認爲PostThread),須要注意的是事件處理函數的訪問權限必須爲public,不然會報異常。ide
這裏咱們更新UI中進度條進度,你們能夠在此取出消息內容執行本身的邏輯。
固然,咱們要記得取消訂閱,跟廣播邏輯很類似。
override fun onDestroy() {
super.onDestroy()
EventBus.getDefault().unregister(this@MainActivity)
}複製代碼
回到上面話題線程模型處,咱們來了解這幾個線程模型具體含義:
在EventBus的事件處理函數中須要指定線程模型,即指定事件處理函數運行所在的想線程。在上面咱們已經接觸到了EventBus的四種線程模型。那他們有什麼區別呢?在EventBus中的觀察者一般有四種線程模型,分別是PostThread(默認)、MainThread、BackgroundThread與Async。
PostThread:若是使用事件處理函數指定了線程模型爲PostThread,那麼該事件在哪一個線程發佈出來的,事件處理函數就會在這個線程中運行,也就是說發佈事件和接收事件在同一個線程。在線程模型爲PostThread的事件處理函數中儘可能避免執行耗時操做,由於它會阻塞事件的傳遞,甚至有可能會引發ANR。
MainThread:若是使用事件處理函數指定了線程模型爲MainThread,那麼不論事件是在哪一個線程中發佈出來的,該事件處理函數都會在UI線程中執行。該方法能夠用來更新UI,可是不能處理耗時操做。
BackgroundThread:若是使用事件處理函數指定了線程模型爲BackgroundThread,那麼若是事件是在UI線程中發佈出來的,那麼該事件處理函數就會在新的線程中運行,若是事件原本就是子線程中發佈出來的,那麼該事件處理函數直接在發佈事件的線程中執行。在此事件處理函數中禁止進行UI更新操做。
Async:若是使用事件處理函數指定了線程模型爲Async,那麼不管事件在哪一個線程發佈,該事件處理函數都會在新建的子線程中執行。一樣,此事件處理函數中禁止進行UI更新操做。
EventBus除了普通事件也支持粘性事件,這個有點相似廣播分類中的粘性廣播。自己粘性廣播用的就比較少,爲了方便理解成訂閱在發佈事件以後,但一樣能夠收到事件。訂閱/解除訂閱和普通事件同樣,可是處理訂閱函數有所不一樣,須要註解中添加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,咱們這裏把註冊這一步放在發送事件的後面,也能夠按照剛纔說的那種方式把註冊步驟放到另一個button點擊事件裏面。
對於粘性廣播咱們都比較清楚屬於常駐廣播,對於EventBus粘性事件也相似,咱們若是再也不須要該粘性事件咱們能夠移除
EventBus.getDefault().removeStickyEvent(MessageEvent(time))
複製代碼
或者調用移除全部粘性事件
EventBus.getDefault().removeAllStickyEvents();
複製代碼
若是對粘性事件還不是很熟悉的同窗能夠再去看看廣播的內容,也能夠將廣播內容跟EventBus作個總結,設計思想及其類似,都是基於觀察者模式,只是粘性體如今可以收到訂閱以前發送的消息。可是它只能收到最新的一次消息,好比說在未訂閱以前已經發送了多條黏性消息了,而後再訂閱只能收到最近的一條消息。
看到這裏,你是否是對EventBus已經有了很好的瞭解,EventBus使用很簡單,可是確實給項目和開發者帶來很大的方便,有機會你們能夠嘗試看看EventBus的源碼,從源碼角度更深層次瞭解EventBus的強大,本節就到這兒,咱們下次再見!!! 晚安