Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android 中 EventBus 的使用(3):多線程事件處理,androideventbus

Android 中 EventBus 的使用(3):多線程事件處理,androideventbus

編輯:關於android開發

Android 中 EventBus 的使用(3):多線程事件處理,androideventbus


在這一系列教程的最後一篇中,我想談談GR的EventBus,在處理多線程異步任務時是多麼簡單而有效。

AsyncTask, Loader和Executor…… 拜托!

Android中有很多種執行異步操作的方法(指平行於UI線程的)。AsyncTask對於用戶來說是最簡單的一種機制,並且只需要少量的設置代碼即可。然而,它的使用是有局限的,正如Android官方文檔中所描述的:

AsyncTask被設計成為一個工具類,在它內部包含了Thread和Handler,但它本身並不是通用線程框架的一部分。AsyncTask應該盡可能地被用在執行一些較短的操作中(最多幾秒)。如果你需要在線程中執行較長時間的任務,那麼建議你直接使用java.util.concurrent包中提供的各種API,如Executor、 ThreadPoolExecutor以及FutureTask。

不過即便是執行短時間的操作也會帶來一些問題,特別是在與Activity/Fragment生命周期有關的地方。由於AsyncTask會持續地運行下去(即使啟動它們的Activity/Fragment已經被銷毀了)。這樣,一旦你在onPostExecute方法中試圖對UI進行更新,那麼最終將導致拋出一個IllegalStateException異常。

Android 3.0中引入了Loader API用來解決Activity/Fragment生命周期的問題(它們的確很有效)。Loader API被設計成向Activity/Fragment中以異步方式加載數據。盡管加載數據是一種非常常見的異步操作,但並非唯一一種需要從UI線程中分開的操作。Loader還需要在Activity/Fragment中實現另外一個監聽接口。盡管這麼做沒有錯,但我個人並不喜歡這種模式(我的意思是最終你的代碼中會包含許多的回調函數,導致代碼的可讀性變得很差)。最後,Activity和Fragment也並非唯一需要對異步操作分線程的地方。例如如果在Service裡,你就不能訪問LoaderManager,所以最終你還是得使用AsyncTask或者java.util.concurrent。

java.util.concurrent包很不錯,我在Android和非Android項目中都可以使用。不過使用時需要對其進行多一點兒配置和管理,不象AsyncTask那麼簡單。你需要對ExecutorService進行初始化,管理和監視它的生命周期,並且可能需要跟一些Future對象打交道。

只要使用恰當,AsyncTask、 Loader和Executor都是非常有效的。但在復雜應用中,需要為每個任務選擇合適的工具,最終你可能三種都會用到。這樣你就得維護三種不同的處理並發的框架代碼。

Green Robot來幫忙了!

GR的EventBus中內置了一個非常棒的並發處理機制。在監聽類中,你可以實現4種不同類型的處理方法。當一個匹配事件被發送過來時,EventBus會根據不同的並發模型將事件發送到相應的處理方法中:

  • onEvent(T event):運行在和被發送事件相同的線程中。
  • onEventMainThread(T event):運行在主(UI)線程中,不管事件從哪個線程中被發送過來。
  • onEventAsync(T event):運行在單獨的線程中,即非UI線程,也非發送事件的線程。
  • onEventBackgroundThread(T event):如果發送事件的線程不是UI線程,則運行在該線程中。如果發送事件的是UI線程,則它運行在由EventBus維護的一個單獨的線程中。多個事件會同步地被這個單獨的後台線程所處理。

這些方法功能強大而且使用簡單。例如有一個比較耗時的操作(可能是網絡調用,大量數據處理等),這一操作需要由UI上的行為來觸發,並且當操作執行完畢後還需對UI進行更新。在這個例子中,UI行為即按鈕點擊,按鈕在activity中,耗時操作在service中。我們可以按下面的方式來實現:

 

        Java   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 SomeActivity.java:   ... @Inject EventBus bus; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { eventBus.post(new DoOperationEvent()); } }); }   @Override protected void onResume() { super.onResume(); bus.register(this); }   @Override protected void onPause() { bus.unregister(this); super.onPause(); }   public void onEventMainThread(OperationCompleteEvent event) { Toast.makeText(this, "Operation complete!", Toast.LENGTH_SHORT).show(); } ...   SomeService.java:   ... @Inject EventBus bus; ... @Override protected void onCreate() { super.onCreate(); bus.register(this); }   @Override protected void onDestroy() { bus.unregister(this); super.onDestroy(); }   public void onEventAsync(DoOperationEvent event){ // DO SOMETHING LONG-RUNNING HERE eventBus.post(new OperationCompleteEvent()); }   ...

盡管這個例子比較簡單,但它卻非常簡明扼要地說明了問題。這裡即不需要實現監聽接口,也不會出現類似生命周期之類的問題(由於activity只能在它存在的時候才能接收到OperationCompleteEvent事件)。除此之外,如果發生了配置改變(旋轉屏幕)或其他什麼原因導致activity在兩次事件發生之間被銷毀並重建,最終仍可以接收到OperationCompleteEvent事件。

此外,我們也可以容易地想到一些其它用法。比如,如果需要將更新進度發出去,你只需另外實現一個封裝了進度值的事件類,然後將其發送出去即可。或者,如果你想讓其它一些事件(不管是相同還是不同類型)不被並行處理(同步執行),你可以選擇使用onEventBackgroundThread。

依賴Bus

實例化EventBus最簡單的方法就是通過EventBus.getDefault()。然而,在EventBusBuilder類(通過EventBus.builder()獲得)中還包含了另外一些有用的配置方法。特別是在本文中提到過的使用你自己的ExecutorService。缺省情況下EventBus通過Executors.newCachedThreadPool()創建自己的ExecutorService,在大多數情況下都已滿足你的需要。然而,有時你可能仍然想要顯示地控制EventBus所使用的線程數量,這種情況下你就可以象下面這樣初始化EventBus:

 

          Java   1 EventBus.builder().executorService(Executors.newFixedTheadPool(NUM_THREADS)).installDefaultEventBus();

 

在EventBusBuilder中另外一些可供配置的是一些和異常處理的有關的控制,以及一個是否允許事件類被繼承的控制開關。這些內容超出了本文所討論的范圍,但我還是建議你仔細去研究一番。GR可能並沒有把這些內容都寫在文檔裡,但如果你讀一讀EventBusBuilder和EventBus的源代碼,相信你會很容易理解它們的。

全能程序員交流QQ群290551701,聚集很多互聯網精英,技術總監,架構師,項目經理!開源技術研究,歡迎業內人士,大牛及新手有志於從事IT行業人員進入!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved