Android開發學習之路-EventBus使用

来源:http://www.cnblogs.com/Fndroid/archive/2016/09/27/5910992.html
-Advertisement-
Play Games

EventBus是一個通過發佈、訂閱事件實現組件間消息傳遞的工具。 它存在的目的,就是為了優化組件之間傳遞消息的過程。傳統組件之間傳遞消息的方法有使用廣播,回調等,而這些方法使用都比較複雜。 工作原理: 依賴: 註:EventBus是事件-訂閱模型,實際上事件就是消息,訂閱就是接收,本文不會很嚴格區 ...


EventBus是一個通過發佈、訂閱事件實現組件間消息傳遞的工具。

它存在的目的,就是為了優化組件之間傳遞消息的過程。傳統組件之間傳遞消息的方法有使用廣播,回調等,而這些方法使用都比較複雜。

工作原理:

依賴:

1 dependencies {
2     compile 'org.greenrobot:eventbus:3.0.0'
3 }

註:EventBus是事件-訂閱模型,實際上事件就是消息,訂閱就是接收,本文不會很嚴格區分,方便理解為主!

1. 從簡單的入手:充當Handler

既然能發送消息,那麼自然在同一個組件下也能進行消息的發送和接收,也就是Handler的職責。

先定義一個事件的對象:

 1 public class MessageEvent {
 2     private String message;
 3 
 4     public MessageEvent(String message) {
 5         this.message = message;
 6     }
 7 
 8     public String getMessage() {
 9         return message;
10     }
11 
12     @Override
13     public String toString() {
14         return message;
15     }
16 }

這個事件對象只需要是Object的子類,沒其他要求,消息的內容可以隨意定,這裡用一個String表示事件的消息,toString直接輸出事件的內容。

在需要接收消息的組件中,進行EventBus的綁定,這裡由Activity充當訂閱者(Subscriber),也就是消息接收者。

 1 public class MainActivity extends AppCompatActivity {
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6         setContentView(R.layout.activity_main);
 7     }
 8 
 9     @Override
10     protected void onStart() {
11         super.onStart();
12         EventBus.getDefault().register(this); // 將當前Activity綁定為訂閱者
13     }
14 
15     @Override
16     protected void onStop() {
17         EventBus.getDefault().unregister(this); // 解綁
18         super.onStop();
19     }
20 
21     // 聲明一個訂閱方法,用於接收事件
22     @Subscribe
23     public void onEvent(MessageEvent messageEvent) {
24         Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
25     }
26 
27 }

通過EventBus.getDefault方法獲取到一個EventBus的一個單例,也就是每次調用這個方法得到的都是同一個EventBus對象。而不同的EventBus對象消息不會互通。

接著需要在Activity的onStart方法中進行對EventBus對象的綁定,在onStop方法中進行解綁。同時,需要定義用於接收事件的方法,並加上@Subscribe註解表明該方法用於接收訂閱事件。

接著,我們需要發送事件:

1 EventBus.getDefault().post(new MessageEvent("I m Fndroid"));

這裡獲取的預設的EventBus對象,通過post方法進行事件的發送,log如下:

 

2. 組件間通訊:代替廣播、回調等

EventBus的存在,並不是為了替代Handler,而是用來進行組件間的通訊。有了上面的知識,接下來就不難了。

我們都知道,只要是同一個EventBus對象綁定的組件(Subscriber),消息是互通的,也就是我們可以在Service中向Activity發送事件進行通訊。(其他組件類似)

定義一個IntentService,並且發送一個事件,而Activity,和上面一樣。

 1 public class MyIntentService extends IntentService {
 2 
 3     public MyIntentService() {
 4         super("MyIntentService");
 5     }
 6 
 7     @Override
 8     protected void onHandleIntent(Intent intent) {
 9         EventBus.getDefault().post(new MessageEvent("From service"));
10     }
11 
12 }

在Activity中開啟服務:

1 startService(new Intent(this, MyIntentService.class));

Log:

組件間的通訊變得如此簡單了。

 

3. 進階:持久事件、線程模式、優先順序

① 持久事件(StickyEvent):對於調用post方法發送的普通消息,會在第一次被接收到的時候被消費掉,也就是我們在@Subscribe方法下處理完了,這個消息就消失了。而EventBus則提供了另一種類型的消息——StickyEvent,這個消息,會被保存在RAM中,直到下一個StickyEvent被髮送才會被替換。每個EventBus對象都能通過geStickyEvent方法獲取最近發出的持久事件。

我們對Activity稍作修改,在訂閱方法中,把當前的持久消息列印出來:

1     // 聲明一個訂閱方法,用於接收事件
2     @Subscribe
3     public void onEvent(MessageEvent messageEvent) {
4         Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
5         Log.d(TAG, "onEvent: Sticky Event = [" + EventBus.getDefault().getStickyEvent(MessageEvent.class) + "]");
6     }

接著對Service也進行修改,令其發送一個StickyEvent:

1     @Override
2     protected void onHandleIntent(Intent intent) {
3         EventBus.getDefault().post(new MessageEvent("From service"));
4         EventBus.getDefault().postSticky(new MessageEvent("From service2"));
5         EventBus.getDefault().post(new MessageEvent("From service3"));
6     }

這裡看到,在第二次發送的時候,調用了postSticky方法發送事件,這就表明瞭該事件是一個持久事件,除非有新的同類型(不同類型的事件可以共存)持久事件被髮送,否則會一直被保存在記憶體中,我們任何時候都能獲取得到。

Log:

可以看到,在第三次接收到消息的時候,將StickyEvent列印出來,依舊是"From service2"。

同樣的,如果我們想要移除此持久事件,可以調用EventBus的removeStickyEvent方法來實現,如果要移除所有類型的持久事件,可以調用removeAllStickyEvent方法。

② 線程模式

EventBus允許我們對訂閱者進行線程設置,預設情況下,訂閱是和事件發送處於同一線程的,我們不妨把訂閱的線程id列印出來看一看。

修改Activity中的@Subscribe方法:

1     @Subscribe
2     public void onEvent(MessageEvent messageEvent) {
3         Log.d(TAG, "onEvent: Thread id = [" + Thread.currentThread().getId() + "]");
4         Log.d(TAG, "onEvent() called with: messageEvent = [" + messageEvent + "]");
5     }

修改Service,讓其發送一次普通事件,並且輸出當前線程id:

1     @Override
2     protected void onHandleIntent(Intent intent) {
3         Log.d(TAG, "onHandleIntent: Thread id = [" + Thread.currentThread().getId() + "]");
4         EventBus.getDefault().post(new MessageEvent("From service"));
5     }

列印Log:

對於訂閱者,有以下四種線程模式:

  1. POSTING:預設模式,訂閱和事件發送在同一線程下進行
  2. MAIN:訂閱在主線程下進行,可以直接修改UI
  3. BACKGROUND:如果事件發送在主線程,則訂閱在子線程下進行,如果事件發送在子線程,則訂閱也在該子線程中進行
  4. ASYNC:如果事件發送在主線程,則訂閱在子線程下進行,如果事件發送在子線程,則訂閱會在其他子線程中進行

設置訂閱者線程很簡單,只需要在註解中賦值即可,如:

1     @Subscribe(threadMode = ThreadMode.MAIN)

③ 優先順序

每個組件中可以有多個訂閱方法,而我們可以對它們設置不同的優先順序,設置的方法也很簡單:

1     @Subscribe(priority = 88)

預設的優先順序為0,更高優先順序的訂閱方法會更先收到事件,而每個訂閱方法都可以對事件進行終止,可以通過以下方法停止事件傳遞:

1    EventBus.getDefault().cancelEventDelivery(messageEvent);

④ 自定義EventBus對象

通過getDefault方法獲取的是一個EventBus預設的單例,而我們可以通過EventBus.Builder來構造一個自定義的EventBus對象。


 

明白了用法以後,我們分析源碼也會更加簡單。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 此外不在更新 地址: ...
  • 實現類似下麵的這種佈局的方法 ...
  • 在上篇文章中實現了優酷菜單的佈局,本文接著實現動畫功能 本文地址:http://www.cnblogs.com/wuyudong/p/5914901.html,轉載請註明源地址。 新建動畫工具類AnimationUtils.java,代碼如下: 接著編寫邏輯部分代碼: 基本實現菜單的旋轉功能 ...
  • 因為我在模仿美圖秀秀的功能,在使用相冊時候,UIImagePickerController本來就是一個UINavigationController的子類,所以沒有辦法使用push,所以做了一個自定義的非UINavigationController子類的相冊。使用的api是ios8以上提供的photo ...
  • 兩類絕對時間[NSDate date]、CFAbsoluteTimeGetCurrent(),或者gettimeofday()。 返回的是從某一個時刻開始,度過的秒數。會隨著用戶設置的系統時間更改。相對時間CACurrentMediaTime 或者-[NSProcessInfo systemUpti... ...
  • 博客撰寫人:It一zhai男 轉載請標明地址:http://www.cnblogs.com/ityizhainan/p/5914487.html 本文將用兩個方法來寫類似汽車荷載的進度 先上截圖 1. 用LinearLayout的addview方法加上for迴圈 1.1 processtest01. ...
  • 本文開始將逐步去實現下麵優酷菜單的效果: 本文地址:http://www.cnblogs.com/wuyudong/p/5912538.html,轉載請註明源地址。 本文首先來實現優酷菜單界面初始化工作 首先使用相對佈局 實現下麵的效果 接著將一些小圖標嵌入裡面,佈局比較簡單有規律 運行後的效果如下 ...
  • 小木學堂專註於企業實戰開發和經驗傳授,所以微信小程式誕生這麼大的事怎麼能不帶著大家一起學習學習呢,所以小木學堂講師連夜趕工學習並實戰開發了微信小應用的第一個程式,並錄製了課程現免費分享給大家。這個速度絕對是國內領先哦,來看看嘗鮮開發,閑話少說,上地址。 線上免費觀看地址 百度雲下載:http://p ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...