訊息傳遞機制之EventBus的使用詳細
EventBus是怎樣管理事件匯流排的, 是不是最佳處理訊息的方案?讓我們一同來學習和認識.
EventBus由來
在面對應用程式內元件間, 元件與後臺執行緒間的通訊. 又如我們在處理耗時操作時, 等到耗時操作完成後通過Handler或者Broadcast去更新UI, 但是面對多個Activity之間需要通過Listener通訊完成. 但是這些問題我們可以通過EventBus來完成.它是通過釋出/訂閱的方式來管理事件匯流排 .通過註解和反射機制將訂閱者連同訂閱函式儲存起來, 然後在傳送訂閱的時候遍歷訂閱函式陣列進行呼叫, 但是這種形式會影響到EventBus的執行效力.
EventBus的介紹
EventBus出自greenrobot, 與GreenDao是一家. 而EventBus3.0框架採用了建造者模式, 並加入註解, 通過註解的方式告知訂閱函式執行在哪一個執行緒中.
EventBus主要角色
- Event 傳遞的事件物件
- Subscriber 事件的訂閱者
- Publisher事件的釋出者
- ThreadMode 定義函式在那種執行緒中執行
官網給出的各種角色的協作圖
EventBus使用
- 在build.gradle中新增引用
compile 'org.greenrobot:eventbus:3.0.0'
2. 定義一個事件型別
public class EventInfoBean { public String msg; public EventInfoBean(String msg) { this.msg = msg; } }
3.訂閱事件
EventBus.getDefault().register(this);
4. 釋出事件
EventBus.getDefault().post(new EventInfoBean("eventBus傳送的訊息"))
5. 解除訂閱(一般放在onDestroy()中)
EventBus.getDefault().unregister(this);
6.訂閱事件處理@Subscribe(threadMode = ThreadMode.MAIN) public void onEventMainThread(EventInfoBean info) { Toast.makeText(getApplicationContext(), "接收到的訊息..." + info.msg, Toast.LENGTH_SHORT).show(); }
7.訂閱事件的優先順序
EventBus事件的優先順序類似於廣播的優先順序, 優先順序越高優先得到訊息
@Subscribe(threadMode = ThreadMode.MAIN,priority = 100)
public void onDataSynEvent(EventInfoBean event) {
Log.e(TAG, "event---->" + event.msg);
}
8.終止事件傳遞
EventBus在傳送有序廣播的時候可以終止廣播的往下傳遞
EventBus.getDefault().cancelEventDelivery(event) ;
9. 程式碼混淆
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
<init>(java.lang.Throwable);
}
EventBus執行緒模型說明
ThreadMode.MAIN
無論任何執行緒中釋出事件, 事件處理函式都會在main執行緒中執行.該方法可以用來更新UI, 但是不能處理耗時操作
ThreadMode.BACKGROUND
如果釋出事件是在UI執行緒中釋出, 那麼事件處理函式會在新的執行緒中執行, 如果釋出事件本來就在子執行緒中釋出的, 那麼事件處理函式在釋出事件的執行緒中執行. 此事件處理函式不可以進行UI更新操作
ThreadMode.POSTING
事件處理和事件釋出在同一個執行緒中. 在事件處理函式中儘量避免執行耗時操作, 因為它會阻塞事件的傳遞, 有可能會引起ANR
ThreadMode.ASYNC
不管事件在哪個執行緒中釋出, 該事件處理函式都會在新建的子執行緒中執行. 事件處理函式中禁止UI更新操作
例項
事件處理函式
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEventMain(FirstEvent firstEvent) {
Log.d(TAG, "接收到的訊息.1.." + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.ASYNC)
public void onMessageEventAsync(FirstEvent firstEvent) {
Log.d(TAG, "接收到的訊息.2.." + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.BACKGROUND)
public void onMessageEventBackground(FirstEvent firstEvent) {
Log.d(TAG, "接收到的訊息.3.." + Thread.currentThread().getName());
}
@Subscribe(threadMode = ThreadMode.POSTING)
public void onMessageEventPosting(FirstEvent firstEvent) {
Log.d(TAG, "接收到的訊息.4.." + Thread.currentThread().getName());
}
從UI執行緒中釋出事件
釋出事件
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EventBus.getDefault().post(new FirstEvent("在同一個執行緒中執行"));
}
});
輸出log
02-27 10:26:29.727 14358-14358/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.1..main
02-27 10:26:29.727 14358-14358/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.4..main
02-27 10:26:29.728 14358-14420/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.2..pool-1-thread-1
02-27 10:26:29.729 14358-14421/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.3..pool-1-thread-2
從子執行緒中釋出事件
釋出事件
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Thread(new Runnable() {
@Override
public void run() {
EventBus.getDefault().post(new FirstEvent("在同一個執行緒中執行"));
}
}).start();
}
});
輸出log
02-27 10:30:45.027 14523-14541/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.3..Thread-799
02-27 10:30:45.027 14523-14541/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.4..Thread-799
02-27 10:30:45.027 14523-14542/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.2..pool-1-thread-1
02-27 10:30:45.036 14523-14523/com.quanzi.eventbusdemo D/SameThreadActivity: 接收到的訊息.1..main
EventBus粘性事件
EventBus的粘性事件類似於廣播中的粘性廣播. 粘性廣播在實際開發中使用的比較少.粘性廣播中訂閱/解除訂閱和普通事件一樣, 但是在處理訂閱函式時需要添加註解 sticky = true
處理粘性事件
@Subscribe(threadMode = ThreadMode.MAIN,sticky = true)
public void onDataSynEvent(FirstEvent event){
Log.d(TAG,"sticky..." + event.getMsg() + "..." + Thread.currentThread().getName());
}
傳送粘性事件
EventBus.getDefault().postSticky(new FirstEvent("粘性事件..."));
移除粘性事件
粘性廣播屬於常駐廣播, 如果不需要可以移除粘性事件
EventBus.getDefault().removeStickyEvent(new FirstEvent());
或呼叫移除所有粘性事件
EventBus.getDefault().removeAllStickyEvents();
EventBus的優缺點
優點 : 簡化了各元件間的通訊方式, 實現瞭解耦讓業務程式碼更加簡潔, 可以動態設定事件處理執行緒以及優先順序
缺點 : 每一個事件必須自定義一個事件類, 造成事件類過多, 從而增加了維護的成本
EventBus3.0與2.X比較
1.程式碼更加簡潔
2.效能更優. 由於EventBus 2.x 是採用反射的方式對整個註冊類中的所有方法進行掃描來完成註冊,因此在效能上有所影響。而EventBus3.0中提供EventBusAnnotationProcessor註解處理器在編譯期通過讀取Subscribe註解並解析、處理其中所包含的資訊,再生成java類來儲存所有訂閱者的資訊,從而比在執行時使用反射來獲得這些訂閱者的資訊速度要快
以上是我個人對EventBus3.0的一些認識和理解,要是有什麼地方不對的,歡迎各位同仁指正
相關推薦
訊息傳遞機制之EventBus的使用詳細
EventBus是怎樣管理事件匯流排的, 是不是最佳處理訊息的方案?讓我們一同來學習和認識.EventBus由來 在面對應用程式內元件間, 元件與後臺執行緒間的通訊. 又如我們在處理耗時操作時, 等到耗時操作完成後通過Handler或者Broadcast去更新UI,
訊息傳遞機制之元件之間訊息傳遞
通常在元件之間傳遞訊息,我們會採用廣播形式 , 自定義介面形式 , EventBus來實現BroadCastReceiver建立廣播private BroadcastReceiver receiver = new BroadcastReceiver() { @Over
Python GUI程式設計之訊息傳遞機制&使用者登入
PythonGUI程式設計之-訊息傳遞機制及簡單的使用者登入 訊息機制 1.訊息的傳遞機制 自動發出事件/訊息 訊息由系統負責傳送到佇列 有相關元件進行繫結/設定 後端自動選擇感興趣的事件並作出相應的
Android訊息傳遞機制分析
1.事件響應機制的預備知識 在深入瞭解Android事件響應機制前,一些預備知識我們應該有所瞭解。 1.1 onTouch是優先於onClick執行,事件傳遞的順序是先經過onTouch,再傳遞到onClick。 1.2 Android中的事件onClick、onLon
【Android 開發】: Android 訊息處理機制之四: Android 訊息迴圈 Looper 及其原始碼解析
上一講我們學習Handler和Message的一些使用方式,我們知道Handler它會發送訊息和處理訊息,並且關聯一個子執行緒,如何傳送訊息入隊和出隊處理訊息等這些都是交給Looper去管理分發的,也就是它是負責整個訊息佇列運轉的一個類,這一講我們就來學習一下Andr
【Android 開發】: Android 訊息處理機制之三: Handler 中 sendMessage() 原始碼剖析
閱讀此文,請先閱讀以下相關連線: sendMessage()的幾種過載方法的使用方式的不同以及它們的原始碼的剖析. 通過前面幾講的內容,我們知道Android不但可以使用非同步任務處理多執行
Handler訊息傳遞機制(子執行緒中傳遞new Handler和主執行緒中new Handle傳遞訊息)
> 子執行緒中更新UI new Thread(new Runnable() { @Override public void run() { Looper.prepare();
Handler訊息傳遞機制(一)簡介
宣告:本教程不收取任何費用,歡迎轉載,尊重作者勞動成果,不得用於商業用途,侵權必究!!! 文章目錄 前言簡介 實戰案例 1、在新啟動的子執行緒傳送訊息 2、在主執行緒中獲取、處理訊息 3、我的demo 和 演示效果 前言簡介 Android的訊息傳遞機制主要是
訊息傳遞機制(通訊)
一 同步和非同步(執行緒) 在維基百科中的釋義是:在計算機程式設計中,非同步,指的是獨立於主程式流發生的事件,以及處理該事件的方式。這些可能是“外部”事件,例如訊號的到達,或由程式發起的操作,該操作與程式同時/併發的執行,而程式不需要阻塞的等待結果。非同步的輸入(input)/輸出(outp
Windows訊息響應機制之三:執行緒與訊息佇列
當一個執行緒第一次被建立時,系統假定執行緒不會用於任何與使用者相關的任務。這樣可以減少執行緒對系統資源的要求。但是,一旦該執行緒呼叫一個與圖形使用者介面有關的函式 ( 如檢查它的訊息佇列或建立一個視窗 ),系統就會為該執行緒分配一些另外的資源,以便它能夠執行與使用者介面有關
Windows訊息響應機制之四:PostQuitMessage和GetMessage函式
Windows是訊息驅動的作業系統。在Windows環境下程式設計必須熟練掌握Windows訊息響應機制。 今天在練習Win32程式設計時碰到一個關於GetMessage函式的問題。這個問題之前一直沒有引起過我的注意,但是今天 在網上搜索發現這個問題很多程式設計師都跟
Handler訊息傳遞機制(一)理解到底為什麼?
1.為什麼UI更新要在主執行緒中,主執行緒有什麼原則? 我們都知道,要在非UI執行緒更新UI需要使用到Handler或者AsyncTask(內部也是Handler實現),那麼為什麼就不能直接在子執行緒中更新UI,而要在UI執行緒中更新。這就扯到一個單執行緒和多
Android 多執行緒程式設計:Handler訊息傳遞機制—重新整理UI主介面
一、為什麼使用Handler 當一個Activity執行的時候,會開啟一條主執行緒,主執行緒主要負責處理與UI相關的事件,主執行緒不允許其他子執行緒操控它,更新UI介面。既然不允許我們在子執行緒中操控UI介面,那麼,像我們平時所見的點選獲取驗證碼,不斷更新
Handler訊息傳遞機制(三)Message訊息的兩種傳送方式
這裡佈局和mainfest的定義省了,直接看樣例 package com.example.message2; import android.app.Activity; import android
理解訊息傳遞機制和訊息轉發機制
訊息傳遞機制 在物件上傳遞方法叫做“傳遞訊息”(pass a message)。訊息有“名稱”(name)或“選擇子”(selector),可以接受引數,而且可能還有返回值。 在Object-c中,如果向物件傳遞訊息,那就會使用動態繫結機制來決定需要呼叫的方
RabbitMQ實戰-訊息確認機制之訊息的正確消費
上節中我們講了如何確保訊息的準確釋出,今天我們來看看如何確保訊息的正確消費。 在之前的基礎上我們對消費者(倉庫服務)進行完善。 修改配置檔案application.yml 消費者的ack方式預設是自動的,也就是說訊息一旦被消費(無論是否處理成功),訊息都會被確認,然後會從
九、rabbitMQ的訊息確認機制之事務機制
說明:在rabbitMQ中,我們為了解決伺服器異常導致資料丟失的問題,我們可以採用rabbitMQ的持久化機制,但是我們如何確定生產者將訊息傳送給了rabbitMQ呢,那麼我們採用兩種協議的模式。 (1)、AMQP實現了事務機制 (2)、confirm模式一、事務
Android訊息傳遞機制---Handler,MessageQueue,Looper.
1.Android訊息機制概述以及背景 (1)Looper、Handler、Messagequeue三者共同實現了android系統裡執行緒間通訊機制。 如在A、B兩個子執行緒之間需要傳遞訊息,首先
引數傳遞機制之JWT
1. 什麼是 JWT JWT 其全稱為:JSON Web Token,簡單地說就是 JSON 在 Web 上的一種帶簽名的標記形式。官方的定義如下: JSON Web Tokens are an open, industry standard RFC 7519 method for representing
windows訊息機制與ASP.net winform控制元件訊息傳遞之滑鼠點選click事件
window系統是一個訊息驅動的系統, windows作業系統本身有自己的訊息佇列,訊息迴圈,它捕捉鍵盤,滑鼠的動作生成訊息,並將這個訊息傳給應用程式的訊息佇列。 當用戶用滑鼠click桌面時,其實使用者是不能直接接觸到某個控制元件的。表面上看,的確是使用者用