EventBus通訊小能手,EventBus通訊能手
1、EventBus簡介
EventBus 是由 greenrobot 組織開發的一個 Android 事件發布/訂閱輕量級架構,特點:代碼簡潔,是一種發布訂閱設計模式(觀察者設計模式)。
EventBus 可以代替 Android 傳統的 Intent, Handler, Broadcast或介面函數,在 Fragment, Activity, Service 線程之間傳遞資料,執行方法。
(可能線程間的簡單通訊看不出EventBus的優勢,但是進程之間通訊代碼繁多,特別是複雜的資料格式,而EventBus能讓通訊變得簡單)
2、EventBus的優勢
1.簡化了組件間的通訊
2.分離了事件的寄件者和接受者
3.在Activity、Fragment和線程中表現良好
4.避免了複雜的和易錯的依賴關係和聲明周期問題
5.使得代碼更簡潔,效能更好
6.更快,更小(約50k的jar包)
3、EventBus大概原理
1.EventBus底層採用的是註解和反射的方式來擷取訂閱者法資訊(首先是註解擷取,若註解擷取不到,再用反射)1
2.當前訂閱者是添加到Eventbus 總的事件訂閱者的subscriptionByEventType集合中
3.訂閱者所有訂閱的事件類型添加到typeBySubscriber 中,方便解註冊時,移除事件
4、使用步驟
1.關聯庫 compile 'org.greenrobot:eventbus:3.0.0'
2.設定許可權(需要連網,用於測試網路請求) <uses-permission android:name="android.permission.INTERNET" />
3. 註冊 EventBus.getDefault().register(this);
4. 發送資訊 EventBus.getDefault().post("這是發送了一條String語句");
5. 接受資訊
@Subscribe() //裡面什麼都沒有表示預設 public void getInfo(String a) { Log.e("擷取到的字串:" ,a); //String a 一般是定義為一個類,簡單的話傳String基本資料格式即可 } // public 不能換成 private
6.退出時記得銷毀註冊
@Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); }
5、案例 demo 點擊下載: http://www.cnblogs.com/wujiancheng
測試主線程與子線程通訊(在子線程中連網請求,在主線程中彈出從子線程發過來的資訊),測試優先順序,測試粘性的作用(Stickly)
1.線程間通訊
發送資訊為EventBus.getDefault().post(new XXX("http://www.tngou.net/api/memo/comment")); //這裡的XXX要對應
那麼接收資訊的為
@Subscribe(threadMode = ThreadMode.ASYNC) public void TestHttp(XXX event){ ......}
EventBus.getDefault().post("I am a String");
接收資訊為
@Subscribe(threadMode = ThreadMode.ASYNC) public void TestHttp(String info){ ......} //隨便寫個String 類型即可
發送資訊url給子線程
@Override public void onClick(View view) { //發送資訊 EventBus.getDefault().post(new HttpEvent("http://www.tngou.net/api/memo/comment")); //這裡需要寫一個解析的類,很簡單只有兩個節點 }
HttpEvent與HttpEvent2代碼一樣,如下:
public class HttpEvent { private String msg; public HttpEvent(String msg) { this.msg = msg; } public String getMsg(){ return msg; }}
子線程發送資訊
//這裡使用XUtils來請求網路,具體的可以下載demo查看
@Subscribe(threadMode = ThreadMode.ASYNC) public void TestHttp(HttpEvent event){ String jsonData = event.getMsg(); //連網請求 Log.e("線程名:" ,Thread.currentThread().getName()); org.xutils.x.http().get(new RequestParams(jsonData), new Callback.CommonCallback<String>() { @Override public void onSuccess(String result) { Log.e("連網請求","連網成功==" + result); Gson gson = new Gson(); JsonData data = gson.fromJson(result,JsonData.class); //發送資訊 EventBus.getDefault().post(new HttpEvent2(data.getMsg() +"-------"+ data.isStatus())); } @Override public void onError(Throwable ex, boolean isOnCallback) { Log.e("連網請求","連網失敗,請檢查網路"); } @Override public void onCancelled(CancelledException cex) { } @Override public void onFinished() { } }); }
接受資訊並顯示出來
@Subscribe(threadMode = ThreadMode.MAIN) public void getMessage(HttpEvent2 event2) { Toast.makeText(this,event2.getMsg(),Toast.LENGTH_SHORT).show(); Log.e("線程名:" ,Thread.currentThread().getName()); }
運行效果如:
子線程請求連網,主線程得到資訊,根據圖下
EventBus3.0 四種線程模式
1.@Subscribe(threadMode = ThreadMode.POSTING)
訂閱者執行的線程與事件的發行者所在的線程為同一個線程,也是EventBus預設的線程模式。
2.@Subscribe(threadMode = ThreadMode.MAIN)
在Android的主線程中運行,不能執行一些耗時的任務。
3.@Subscribe(threadMode = ThreadMode.BACKGROUND)
在後台線程中執行,如果發行者是在主線程中進行的事件發布,那麼訂閱者將會重新開啟一個子線程運行
若是發行者在不是在主線程中進行的事件發布,那麼這時候訂閱者就在發行者所在的線程中執行任務。
4.@Subscribe(threadMode = ThreadMode.ASYNC),
在獨立的線程中執行,不管發行者是在主線程還是在子線程中進行事件的發布,訂閱者都是在重新開啟一個線程來執行任務
2.測試優先順序
priority (預設優先順序為0)越大優先順序越大,即最先執行。必須在同一個線程中測試,兩個線程沒有優先順序的可比性.
發送資訊
@Override public void onClick(View view) { EventBus.getDefault().post(new HttpEvent3("測試優先順序")); }
接收資訊
@Subscribe(priority =88 ) public void getPriority(HttpEvent3 event3) { Log.e("priority =88:" ,event3.getMsg()); } @Subscribe(priority =10 ) public void getPriority2(HttpEvent3 event3) { Log.e("priority =10:" ,event3.getMsg()); } @Subscribe(priority =77 ) public void getPriority3(HttpEvent3 event3) { Log.e("priority =77:" ,event3.getMsg()); EventBus.getDefault().cancelEventDelivery(event3); //中斷事件傳遞 } @Subscribe(priority =99 ) public void getPriority4(HttpEvent3 event3) { Log.e("priority =99:" ,event3.getMsg()); }
優先順序只有三個,從大到小的順序執行,因為再77的時候中斷事件傳遞,所以沒有priority =10
3.測試粘性的作用
粘性EventBus類型與粘性broadcast,在不註冊的情況下發送資訊,資訊會緩衝這,當註冊的時候,能接收到之前發的資訊
//測試粘性EventBus.getDefault().postSticky("測試粘性Stickly"); //通過postSticky發送//註冊EventBus.getDefault().register(this);
接收資訊
@Subscribe(sticky = true) public void getStickly(String a) { Log.e("sticky = true:" ,a); } @Subscribe(sticky = false) public void getStickly2(String a) { Log.e("sticky = false:" ,a); }
// sticky = true 才能收到資訊