標籤:文章 簡單 嚴格 傳遞 instance click lan view arp
一.引言
與四大組件之一的BroadCast廣播比較,廣播主要監聽系統級事件,比如網路切換,電池電量等屬於進程間的通訊,EventBus 是進程內的通訊。
瞭解BroadCast 可以查看該文章:Android 四大組件 (三) BroadcastReceiver 介紹二.基本使用 引入類庫:
compile ‘com.jakewharton:butterknife:8.5.1‘
頁面開啟時候初始化並註冊EventBus
//初始化 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //註冊 EventBus EventBus.getDefault().register(this); }
頁面銷毀時候解除EventBus註冊
//銷毀 EventBus @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); }
發布事件 publish
//發布事件 EventBus.getDefault().post(new EventBean("我來自第二個頁面的觸發"));
接受者 subscribe.注意方法名可以隨便取,但是參數類型與publish發行者的保持一致. 這裡是EventBean
//訂閱者事件,處理事件反饋的訊息 @Subscribe public void OnEvent(EventBean bean) { //拿到發行者傳過來的event事件帶的訊息 String msgStr = bean.getMsg(); //UI列印出拿到的訊息 tvFirst.setText(msgStr); }
三.ThreadMode 分析 五種 ThreadMode介紹
ThreadMode.MAIN 訂閱者將在Android的主線程(有時稱為UI線程)中被調用。如果發布線程是主線程,則將直接呼叫事件處理常式方法(與ThreadMode.POSTING中描述的同步)。使用此模式的事件處理常式必須快速返回以避免阻塞主線程. ThreadMode.MAIN_ORDERED 訂閱者將在Android的主線程中被調用。該事件總是排隊等待以後傳遞給訂閱者。這給事件處理一個更嚴格和更一致的順序(因此名字MAIN_ORDERED)。例如,如果使用MAIN線程模式在事件處理常式中發布另一個事件,則第二個事件處理常式將在第一個事件處理常式之前完成(因為它被同步調用 - 將其與方法調用進行比較)。使用MAIN_ORDERED,第一個事件處理常式將完成,然後第二個將在稍後的時間點被調用(只要主線程有能力). ThreadMode.BACKGROUND 訂閱者將在後台線程中被調用。如果發布線程不是主線程,則會在發布線程中直接呼叫事件處理常式方法。如果發布線程是主線程,則EventBus將使用一個後台線程來按順序發送所有事件。使用這種模式的事件處理常式應該儘快返回以避免阻塞後台線程。 ThreadMode.ASYNC 事件處理常式方法在單獨的線程中調用。這總是獨立於發布線程和主線程。發布事件永遠不會等待使用此模式的事件處理常式方法。事件處理常式方法應該使用這種模式,如果它們的執行可能需要一些時間,例如網路訪問。避免同時觸發大量長時間啟動並執行非同步處理常式方法來限制並發線程的數量。EventBus使用線程池有效地重用已完成非同步事件處理常式通知中的線程。 ThreadMode.POSTING這是預設的。訂閱者將在發布該事件的同一個線程中被調用。事件傳遞是同步完成的,所有訂閱者一旦發布完成就被調用。這個ThreadMode意味著最小的開銷,因為它避免了完全的線程切換。因此,對於已知完成的簡單任務而言,這是推薦的模式,其時間很短,不需要主線程。使用這種模式的事件處理常式應該快速返回以避免阻塞發布線程,這可能是主線程。
源碼查看下五種ThreadMode不同處理方式:
private void postToSubscription(Subscription subscription, Object event, boolean isMainThread) { switch (subscription.subscriberMethod.threadMode) { //發送和訂閱者在同一線程內 case POSTING: invokeSubscriber(subscription, event); break; //主線程 case MAIN: if (isMainThread) { invokeSubscriber(subscription, event); } else { mainThreadPoster.enqueue(subscription, event); } break; // case MAIN_ORDERED: if (mainThreadPoster != null) { mainThreadPoster.enqueue(subscription, event); } else { // temporary: technically not correct as poster not decoupled from subscriber invokeSubscriber(subscription, event); } break; //後台,不能並發處理 case BACKGROUND: if (isMainThread) { backgroundPoster.enqueue(subscription, event); } else { invokeSubscriber(subscription, event); } break; //子線程 非同步並發處理 case ASYNC: asyncPoster.enqueue(subscription, event); break; default: throw new IllegalStateException("Unknown thread mode: " + subscription.subscriberMethod.threadMode); } }
四.粘性事件 簡單說就是: 發送事件之後再訂閱該事件也能收到該事件。同樣Android 中也有同樣的粘性事件機制,如 粘性廣播(Sticky Broadcast). 粘性事件使用情境:
一些事件進行資訊感興趣的事件後發布。 例如,一個事件訊號,一些初始化完成。 或者如果你有感應器位置資料和你想抓住最近的值。 而不是實現自己的緩衝,您可以使用黏性的事件。 EventBus保持過去的事件的特定類型在記憶體中。 黏性的事件可以交付給使用者或顯式查詢。 因此,你不需要任何特殊的邏輯來考慮可用的資料。
粘性使用樣本:
// 1建立一個粘性事件類別 public class StickyEvent { public String msg; public StickyEvent(String msg) { this.msg = msg; } }
// 2 發送粘性事件 EventBus.getDefault().postSticky(new StickyEvent("我是粘性事件"));
// 3 接收粘性事件 @Subscribe(threadMode = ThreadMode.MAIN, sticky = true) public void StickyEventBus(StickyEvent event){ // 顯示接收的資料 tv_eventbus_send_result.setText(event.msg); }
// 4.接收粘性事件數目據按鈕的點擊事件處理 bt_eventbus_send_sticky.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //true第一次點擊,防止重複註冊 if(isFirstFlag) { isFirstFlag = false; // 4 註冊 EventBus.getDefault().register(EventBusSendActivity.this); } } });
@Override protected void onDestroy() { super.onDestroy(); // 5 解註冊 EventBus.getDefault().removeAllStickyEvents(); EventBus.getDefault().unregister(EventBusSendActivity.this); }
Android 開源架構 ( 七 ) 事件匯流排---EventBus