安卓開發筆記——探索EventBus
1、關于EventBus:
組件通訊在Android開發中是不可避免的,隨著業務需求的復雜化,代碼中需要我們去處理的業務邏輯難度也不斷增大。例如多個Fragment之間的數據傳遞,Service與Activity、Fragment之間的通訊,BroadCast與Activity、Fragment之間的通訊,各種startActivityForResult的使用,繁雜的操作令我們所厭倦,在GitHub上找了下解決方案,發現了一個不錯的開源庫EventBus,相信很多做過Android開發的朋友都或多或少對此有所了解。
EventBus是一款針對Android優化的發布/訂閱事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息.優點是開銷小,代碼更優雅。以及將發送者和接收者解耦。
這是EventBus在GitHub上的開源庫地址:https://github.com/greenrobot/EventBus
EventBus的大體關系是這樣的:訂閱者(Subscriber)通過訂閱事件(Event)到總線,事件發布者(Publisher)發布事件(Event)到總線被訂閱者(Subscriber)接收,其實說白了就是軟件設計模式里的觀察者模式。EventBus在使用的時候就是在合適的地方發布一個事件,使得注冊了該事件接收的對象就可以收到通知,進行相應的操作。
2、初探EventBus:
文縐縐的文字描述令人厭煩,直接上代碼說話吧,先來看下要實現的效果:
看似很簡單的效果,點擊按鈕跳轉界面,利用Intent發送一個消息,然后TextView接收顯示。這是傳統上的做法,如果真是這樣做,那么寫這篇文章的就完全沒意義了。其實這里就是利用到了EventBus,并沒有用到Intent來傳遞消息。
先來看下具體的代碼(記得添加EventBus的引用),然后我再分部來解析:
上面的代碼很簡單,這里只是拋磚引玉并不做太多復雜的操作,大家可以根據自己的項目需求來添加對應的代碼。
3、解析代碼:
1、注冊EventBus:
在添加EventBus的引用后,我們就可以對任意類進行注冊綁定和解綁EventBus事件,注冊方法和反注冊方法很簡單,在上面的代碼中就可以看出來了,分別是register和unregister,這里的EventBus.getDefault是獲取到EventBus實例的意思(單例)。
1 //注冊綁定EventBus 2 EventBus.getDefault().register(this); 3 //解綁EventBus 4 EventBus.getDefault().unregister(this);
2、EventBus事件:
EventBus很靈活,它對事件不進行任何的限制,也不需要繼承或者實現任何類或者接口,可以是任意類型的實體類,好比上面代碼提到的MyEvent。
3、EventBus事件發布者:
有了事件之后,我們就可以對事件進行發布,然后可以被訂閱這個事件的所有訂閱者所接收。發送事件很簡單,有兩種方法post與postSticky:
1 //立即發送事件 2 EventBus.getDefault().post(Object event); 3 //延遲發送事件 4 EventBus.getDefault().postSticky(Objet event);
4、EventBus事件訂閱者:
EventBus的事件訂閱者可以是任何已經進行注冊EventBus的類,訂閱者的數量是沒有上限的(很重要,下文會提到),這里的訂閱有4種方法,這里都是由onEvent開頭的,有著一定的區別:
1、onEvent:
如果使用onEvent作為訂閱函數,那么該事件在哪個線程發布出來的,onEvent就會在這個線程中運行,也就是說發布事件和接收事件線程在同一個線程。使用這個方法時,在onEvent方法中不能執行耗時操作,如果執行耗時操作容易導致事件分發延遲。
2、onEventMainThread:
如果使用onEventMainThread作為訂閱函數,那么不論事件是在哪個線程中發布出來的,onEventMainThread都會在UI線程中執行,接收事件就會在UI線程中運行,這個在Android中是非常有用的,因為在Android中只能在UI線程中跟新UI,所以在onEvnetMainThread方法中是不能執行耗時操作的。
3、onEventBackground:
如果使用onEventBackgrond作為訂閱函數,那么如果事件是在UI線程中發布出來的,那么onEventBackground就會在子線程中運行,如果事件本來就是子線程中發布出來的,那么onEventBackground函數直接在該子線程中執行。
4、onEventAsync:
使用這個函數作為訂閱函數,那么無論事件在哪個線程發布,都會創建新的子線程在執行onEventAsync。
1 public void onEvent(Object event) {} 2 public void onEventMainThread(Object event) {} 3 public void onEventBackgroundThread(Object event) {} 4 public void onEventAsync(Object event) {}
介紹完EventBus里的所有角色后,我們來理一理訂閱/被訂閱流程:
首先,要想成為事件訂閱者需要先對EventBus進行注冊綁定,然后在本類需要去寫一個以onEvent開頭的方法來接收處理消息事件,再來我們需要一個自定義的事件可以讓事件的發布者發布,讓事件的訂閱者接收。事件的發布可以通過post方法或者是postSticky方法發布。
4、EventBus所帶來的一些方便之處:
EventBus是一款針對Android優化的發布/訂閱事件總線。主要功能是替代Intent,Handler,BroadCast在Fragment,Activity,Service,線程之間傳遞消息.優點是開銷小,代碼更優雅。以及將發送者和接收者解耦。這是我們在文章開頭所介紹過的,這里就不多說了,說幾個在實際開發中所運用到的地方。
例如:
1、當某個頁面的某些值發生變化的時候,需要去同時去更改多個頁面相對應的值,這時候只要這些類注冊訂閱了該事件,那么我們就可以很輕松通過post發送消息來進行通訊。
2、某些時候,我們并不希望發布出來的Event立即被消費掉,而是等到時機成熟。比如說,在一個詳情頁點贊之后,產生一個事件,這個事件并不立即被消費,而是等用戶退出詳情頁回到商品列表之后,接收到該事件,然后刷新Adapter等。其實這就是之前我們用startActivityForResult和onActivityResult做的事情。這里我們就可以利用postSticky來實現這樣的機制。
總之,EventBus極大的減輕了我們各種組件之間的通訊復雜度,也大大減少了使用ActivityForResult的麻煩。真實值得極力推薦。
5、理解EventBus
從源碼中我們可以知道,當我們在類中注冊綁定EventBus的時候,它會去掃描當前類并記錄下所有已onEvent開頭的方法,存放在一個Map<Key,Value>中,在事件通過post發布之后,EventBus會根據post中實參的類型,去Map中查找對應的方法,并找到了對應的Thread,最終利用Java的反射機制去執行我們的方法。
onEventMainThread表示這個方法會在UI主線程執行。
onEventPostThread表示這個方法會在當前發布事件的線程中執行。
BackgroundThread表示如果在非UI主線程發布的事件,則直接執行,和發布在同一個線程中。如果在UI線程發布的事件,則加入后臺任務隊列,使用線程池一個接一個調用。
Async 加入后臺任務隊列,使用線程池調用,注意沒有BackgroundThread中的一個接一個。