標籤:
1.EventBus優缺點
EventBus 作為 Android 開發中常用的架構,擁有著許多優點:
調度靈活。不依賴於 Context,使用時無需像廣播一樣關注 Context 的注入與傳遞。父類對於通知的監聽和處理可以繼承給子類,這對於簡化代碼至關重要;通知的優先順序,能夠保證 Subscriber 關注最重要的通知;粘滯事件(sticky events)能夠保證通知不會因 Subscriber 的不在場而忽略。可繼承、優先順序、粘滯,是 EventBus 比之於廣播、觀察者等方式最大的優點,它們使得建立結構良好組織緊密的通知系統成為可能。
使用簡單。EventBus 的 Subscriber 註冊非常簡單,調用 eventBus 對象的 register 方法即可,如果不想建立 eventBus 還可以直接調用靜態方法 EventBus.getDefault() 擷取預設執行個體,Subscriber 接收到通知之後的操作放在 onEvent 方法裡就行了。成為 Publisher 的過程就更簡單了,只需要調用合適的 eventBus(自己建立的或是預設的)的 post 方法即可。
快速且輕量。作為 github 的明星項目之一, EventBus 的原始碼中許多技巧來改善效能;
- eventbus的 缺點是他的代碼邏輯不是很清楚,在 Subscriber 註冊的時候,Subscriber 中的方法會被遍曆尋找以 onEvent 開頭的 public 方法。這將帶來一些問題,一旦對代碼進行混淆,就無法尋找到了。好訊息是 EventBus 已經打算使用註解來實現,這應該能夠解決代碼混淆的問題。
但有一個缺點是觀察者專屬的,那就是觀察者可能會造成介面的膨脹。特別是當程式要求大量形式各異的通知,而程式員有沒有做出良好的抽象時,代碼中會包含大量的介面,介面數量的增長又會帶來命名、注釋等等一大堆問題。本質上說觀察者要求程式員從零開始實現事件的產生、分發與處理過程,這就要求參與者必須對整個通知過程有著良好的理解。當程式碼適量時,這是一個合理的要求,然而當程式太大時,這將成為一種負擔。
下面我們實現這一一個效果,A頁面跳轉到B頁面,B頁面發送通知更新A頁面的textView的字型顏色(顏色值隨機),如下:
2.項目結構
3.activity_main.xml
放了一個按鈕和一個顯示文字的TextView,跳轉到nextactivity的按鈕
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center" tools:context="${relativePackage}.${activityClass}" > <Button android:id="@+id/btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="16sp" android:text="Jump NextActivity" /> <TextView android:id="@+id/color_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:textSize="18sp" android:text="這是一段可以被改變字型顏色的文字" /></LinearLayout>
4.ChangeTextColorEvent.java
定義事件類別,擷取顏色和當前的activity
/** * * <改變顏色的Event> * * @author wangkeke * @version [V1.00, 2016年5月10日] * @see [相關類/方法] * @since V1.00 */public class ChangeTextColorEvent{ private String color; private Activity activity; public ChangeTextColorEvent(String color, Activity activity) { super(); this.color = color; this.activity = activity; } public String getColor() { return color; } public Activity getActivity() { return activity; }}
5.MainActivity.java
代碼非常簡單,註冊EventBus,反註冊EventBus,onEventMainThread用於接收訂閱的事件
public class MainActivity extends Activity{ private Button button; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //註冊EventBus EventBus.getDefault().register(this); initView(); } private void initView() { button = (Button)findViewById(R.id.btn); textView = (TextView)findViewById(R.id.color_text); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //跳轉到NextActivity Intent intent = new Intent(MainActivity.this, NextActivity.class); startActivity(intent); } }); } /** * public修飾,不能使用static abstart修飾 * 參數只能有一個 * @param event * @see [類、類#方法、類#成員] */ @Subscribe public void onEventMainThread(ChangeTextColorEvent event) { textView.setTextColor(Color.parseColor(event.getColor())); //finish NextActivity event.getActivity().finish(); } @Override protected void onDestroy() { super.onDestroy(); //反註冊EventBus EventBus.getDefault().unregister(this); }}
6.activity_next.xml
定義一個發送訊息的按鈕
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="16sp" android:text="發送改變字型顏色的Event" /></RelativeLayout>
7.NextActivity.java
public class NextActivity extends Activity{ private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_next); initView(); } private void initView() { button = (Button)findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(NextActivity.this, getRandColorCode(), Toast.LENGTH_SHORT).show(); //發送訊息 EventBus.getDefault().post(new ChangeTextColorEvent(getRandColorCode(), NextActivity.this)); } }); } /** * 擷取十六進位的顏色代碼.例如 "#6E36B4" * * @return String */ public static String getRandColorCode() { String r, g, b; Random random = new Random(); r = Integer.toHexString(random.nextInt(256)).toUpperCase(); g = Integer.toHexString(random.nextInt(256)).toUpperCase(); b = Integer.toHexString(random.nextInt(256)).toUpperCase(); r = r.length() == 1 ? "0" + r : r; g = g.length() == 1 ? "0" + g : g; b = b.length() == 1 ? "0" + b : b; return "#"+r + g + b; }}
8.接收函數
EventBus除了可以使用onEventMainThread()函數接收之外,其實EventBus還有另外幾個不同的函數,他們分別是:
1、onEvent
2、onEventMainThread
3、onEventBackgroundThread
4、onEventAsync
四種訂閱函數都是使用onEvent開頭的,它們的功能稍有不同,在介紹不同之前先介紹兩個概念:
告知觀察者事件發生時通過EventBus.post函數實現,這個過程叫做事件的發布,觀察者被告知事件發生叫做事件的接收,是通過下面的訂閱函數實現的。
- onEvent:如果使用onEvent作為訂閱函數,那麼該事件在哪個線程發布出來的,onEvent就會在這個線程中運行,也就是說發布事件和接收事件線程在同一個線程。使用這個方法時,在onEvent方法中不能執行耗時操作,如果執行耗時操作容易導致事件分發延遲。
- onEventMainThread:如果使用onEventMainThread作為訂閱函數,那麼不論事件是在哪個線程中發布出來的,onEventMainThread都會在UI線程中執行,接收事件就會在UI線程中運行,這個在Android中是非常有用的,因為在Android中只能在UI線程中跟新UI,所以在onEvnetMainThread方法中是不能執行耗時操作的。
- onEventBackground:如果使用onEventBackgrond作為訂閱函數,那麼如果事件是在UI線程中發布出來的,那麼onEventBackground就會在子線程中運行,如果事件本來就是子線程中發布出來的,那麼onEventBackground函數直接在該子線程中執行。
- onEventAsync:使用這個函數作為訂閱函數,那麼無論事件在哪個線程發布,都會建立新的子線程在執行onEventAsync.
備忘:
1.EventBus-v3.0.1.jar下載.
2.本文例子源碼下載.
參考文章:
1.BroadcastReceiver、EventBus的優缺點.
2.EventBus使用詳解(一)——初步使用EventBus.
【Android】EventBus兩分鐘入門執行個體