亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android 中 EventBus 的使用之多線程事件處理

 更新時(shí)間:2015年11月18日 09:59:01   投稿:mrr  
這篇文章主要介紹了Android 中 EventBus 的使用之多線程事件處理的相關(guān)資料,需要的朋友可以參考下

在這一系列教程的最后一篇中,我想談?wù)凣R的EventBus,在處理多線程異步任務(wù)時(shí)是多么簡(jiǎn)單而有效。

AsyncTask, Loader和Executor…… 拜托!

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

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

不過即便是執(zhí)行短時(shí)間的操作也會(huì)帶來一些問題,特別是在與Activity/Fragment生命周期有關(guān)的地方。由于AsyncTask會(huì)持續(xù)地運(yùn)行下去(即使啟動(dòng)它們的Activity/Fragment已經(jīng)被銷毀了)。這樣,一旦你在onPostExecute方法中試圖對(duì)UI進(jìn)行更新,那么最終將導(dǎo)致拋出一個(gè)IllegalStateException異常。

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

java.util.concurrent包很不錯(cuò),我在Android和非Android項(xiàng)目中都可以使用。不過使用時(shí)需要對(duì)其進(jìn)行多一點(diǎn)兒配置和管理,不象AsyncTask那么簡(jiǎn)單。你需要對(duì)ExecutorService進(jìn)行初始化,管理和監(jiān)視它的生命周期,并且可能需要跟一些Future對(duì)象打交道。

只要使用恰當(dāng),AsyncTask、 Loader和Executor都是非常有效的。但在復(fù)雜應(yīng)用中,需要為每個(gè)任務(wù)選擇合適的工具,最終你可能三種都會(huì)用到。這樣你就得維護(hù)三種不同的處理并發(fā)的框架代碼。

Green Robot來幫忙了!

GR的EventBus中內(nèi)置了一個(gè)非常棒的并發(fā)處理機(jī)制。在監(jiān)聽類中,你可以實(shí)現(xiàn)4種不同類型的處理方法。當(dāng)一個(gè)匹配事件被發(fā)送過來時(shí),EventBus會(huì)根據(jù)不同的并發(fā)模型將事件發(fā)送到相應(yīng)的處理方法中:

onEvent(T event):運(yùn)行在和被發(fā)送事件相同的線程中。
onEventMainThread(T event):運(yùn)行在主(UI)線程中,不管事件從哪個(gè)線程中被發(fā)送過來。
onEventAsync(T event):運(yùn)行在單獨(dú)的線程中,即非UI線程,也非發(fā)送事件的線程。
onEventBackgroundThread(T event):如果發(fā)送事件的線程不是UI線程,則運(yùn)行在該線程中。如果發(fā)送事件的是UI線程,則它運(yùn)行在由EventBus維護(hù)的一個(gè)單獨(dú)的線程中。多個(gè)事件會(huì)同步地被這個(gè)單獨(dú)的后臺(tái)線程所處理。

這些方法功能強(qiáng)大而且使用簡(jiǎn)單。例如有一個(gè)比較耗時(shí)的操作(可能是網(wǎng)絡(luò)調(diào)用,大量數(shù)據(jù)處理等),這一操作需要由UI上的行為來觸發(fā),并且當(dāng)操作執(zhí)行完畢后還需對(duì)UI進(jìn)行更新。在這個(gè)例子中,UI行為即按鈕點(diǎn)擊,按鈕在activity中,耗時(shí)操作在service中。我們可以按下面的方式來實(shí)現(xiàn):

Java

盡管這個(gè)例子比較簡(jiǎn)單,但它卻非常簡(jiǎn)明扼要地說明了問題。這里即不需要實(shí)現(xiàn)監(jiān)聽接口,也不會(huì)出現(xiàn)類似生命周期之類的問題(由于activity只能在它存在的時(shí)候才能接收到OperationCompleteEvent事件)。除此之外,如果發(fā)生了配置改變(旋轉(zhuǎn)屏幕)或其他什么原因?qū)е耡ctivity在兩次事件發(fā)生之間被銷毀并重建,最終仍可以接收到OperationCompleteEvent事件。

此外,我們也可以容易地想到一些其它用法。比如,如果需要將更新進(jìn)度發(fā)出去,你只需另外實(shí)現(xiàn)一個(gè)封裝了進(jìn)度值的事件類,然后將其發(fā)送出去即可?;蛘?,如果你想讓其它一些事件(不管是相同還是不同類型)不被并行處理(同步執(zhí)行),你可以選擇使用onEventBackgroundThread。

依賴Bus

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

Java

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

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

相關(guān)文章

最新評(píng)論