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的引用),然后我再分部來解析:

1 package com.lcw.rabbit.eventbusdemo.eventbusdemo; 2 3 import android.content.Intent; 4 import android.os.Bundle; 5 import android.support.v7.app.AppCompatActivity; 6 import android.view.View; 7 import android.widget.Button; 8 import android.widget.TextView; 9 10 import de.greenrobot.event.EventBus; 11 12 public class MainActivity extends AppCompatActivity { 13 14 private Button mBt_1; 15 private TextView mTv_1; 16 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_main); 21 //注冊綁定EventBus 22 EventBus.getDefault().register(this); 23 24 initView(); 25 initAction(); 26 27 } 28 29 private void initAction() { 30 mBt_1.setOnClickListener(new View.OnClickListener() { 31 @Override 32 public void onClick(View v) { 33 startActivity(new Intent(MainActivity.this, SecondActivity.class)); 34 } 35 }); 36 } 37 38 private void initView() { 39 mBt_1 = (Button) findViewById(R.id.bt_1); 40 mTv_1 = (TextView) findViewById(R.id.tv_info1); 41 } 42 43 44 //接收所訂閱的消息 45 public void onEventMainThread(MyEvent myEvent) { 46 if (myEvent.getInfo()!=null) { 47 mTv_1.setText(myEvent.getInfo()); 48 } 49 50 } 51 52 53 @Override 54 protected void onDestroy() { 55 super.onDestroy(); 56 //解綁EventBus 57 EventBus.getDefault().unregister(this); 58 } 59 }

1 package com.lcw.rabbit.eventbusdemo.eventbusdemo; 2 3 import android.os.Bundle; 4 import android.support.v7.app.AppCompatActivity; 5 import android.view.View; 6 import android.widget.Button; 7 import android.widget.Toast; 8 9 import de.greenrobot.event.EventBus; 10 11 public class SecondActivity extends AppCompatActivity { 12 13 private Button mBt_2; 14 15 @Override 16 protected void onCreate(Bundle savedInstanceState) { 17 super.onCreate(savedInstanceState); 18 setContentView(R.layout.activity_second); 19 initView(); 20 initAction(); 21 22 } 23 24 private void initAction() { 25 mBt_2.setOnClickListener(new View.OnClickListener() { 26 @Override 27 public void onClick(View v) { 28 Toast.makeText(SecondActivity.this,"消息已發送",Toast.LENGTH_SHORT).show(); 29 EventBus.getDefault().post(new MyEvent("我是被發送過來的消息")); 30 31 } 32 }); 33 } 34 35 private void initView() { 36 mBt_2 = (Button) findViewById(R.id.bt_2); 37 } 38 39 40 }

1 package com.lcw.rabbit.eventbusdemo.eventbusdemo; 2 3 /** 4 * Created by Lichenwei 5 * Date: 2015-10-11 6 * Time: 18:23 7 */ 8 public class MyEvent { 9 10 private String info; 11 12 public MyEvent(String info) { 13 this.info = info; 14 } 15 16 public String getInfo() { 17 return info; 18 } 19 20 public void setInfo(String info) { 21 this.info = info; 22 } 23 }
上面的代碼很簡單,這里只是拋磚引玉並不做太多復雜的操作,大家可以根據自己的項目需求來添加對應的代碼。
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中的一個接一個。
作者:李晨瑋
出處:http://www.cnblogs.com/lichenwei/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,日后必有一番作為!旁邊有“推薦”二字,你就順手把它點了吧,相得准,我分文不收;相不准,你也好回來找我!