AsyncTask與Thread+Handler簡要分析
!個人研究探索整理
非同步處理
目的:提高程式響應性
體現:
耗時操作
網路資料(圖片)載入
資料庫查詢
複雜業務邏輯處理
開發中涉及UI的操作必須遵守單執行緒模型的原則,因為Android的UI操作並非執行緒安全,並且這些操作必須在UI執行緒中執行。
單執行緒模型的兩條法則:
1. 不要阻塞UI執行緒
2. 確保只在UI執行緒中訪問Android UI工具包
幾種其他執行緒訪問主執行緒的方法
[程式碼]java程式碼:
1 2 3 4 5 6 7 |
|
當需要實現一些很複雜的操作並需要頻繁地更新UI時以上的方法會變的很繁瑣。 所以,Android 1.5提供了一個工具類:AsyncTask,方便處理長時間執行的任務,並操作UI。相對來說AsyncTask更輕量級一些,不需要藉助執行緒和Handler即可實現簡單的非同步處理。 但AsyncTask也並不完美,如當網路情況較差,非同步任務不能儘快完成執行的情況下,新開的執行緒會造成介面不流暢,當開啟的執行緒過多時,還可能出現FC。
AsyncTask
特點:
AsyncTask的規範型很強,能夠時時反映更新的情況,Task在主執行緒之外執行,回撥方法在主執行緒執行。
內部實現原理:
本質是一個執行緒池,所有提交的非同步任務都會在這個執行緒池中的工作執行緒內執行,當工作執行緒需要跟UI執行緒互動時,工作執行緒會傳遞訊息到UI執行緒建立的Handler,由Handler呼叫相關的回撥方法,實現UI介面的更新。
成員變數:
[程式碼]java程式碼:
01 02 03 04 05 06 07 08 09 10 11 12 13 |
|
//執行緒池是靜態變數,所有的非同步任務都會放到這個執行緒池的工作執行緒中執行
我們在new AsyncTask();例項化的時候,會呼叫父類的AsyncTask()建構函式
建構函式:
建構函式引數:三種泛型型別
1.Params:傳遞給後臺任務的引數型別,比如HTTP請求的URL
2.Progress:後臺計算執行過程中,進度單位的型別(就是後臺程式已經執行了百分之幾了)。
3.Result:後臺執行返回的結果的型別,比如String,List等
通常我們使用Void標識不使用的型別
任務的當前狀態:
在一個任務的生命週期內,每個狀態只會設定一次
PENDING 尚未執行
RUNNING 正在執行
FINISHED 表示onPostExecute已經完成
後臺執行緒執行的五個狀態:
1、準備執行,2、正在後臺執行,3、進度更新,4、完成後臺任務,5、取消任務
對應的回撥方法(我們需要做的就是實現這些方法):
1、準備執行:onPreExecute(),該回撥方法在任務被execute()提交到執行緒池之後立即由UI執行緒呼叫。這個步驟通常用來做一些準備工作,在UI上顯示進度條等。
2、正在後臺執行:doInBackground(Params...),該回撥方法由後臺執行緒在onPreExecute()方法執行結束後立即呼叫。通常在這裡執行耗時的後臺計算,計算的結果必須由該方法返回,並被傳遞到onPostExecute()中。在該方法內也可使用publishProgress(Progress...)來釋出一個或多個進度單位(units of progress),這些值將會在onProgressUpdate(Progress...)中被髮布到UI執行緒,該方法為抽象方法,子類必須實現。
3. 進度更新:onProgressUpdate(Progress...),該方法由UI執行緒在publishProgress(Progress...)方法呼叫完後被呼叫,一般用於動態地顯示一個進度條。
4. 完成後臺任務:onPostExecute(Result),當後臺計算結束後呼叫。後臺計算的結果會被作為引數傳遞給該方法。
5、取消任務:onCancelled (),執行在UI執行緒,在AsyncTask的cancel()方法後執行,可在取消執行緒操作時呼叫
要取消正在執行的任務時:檢查asynctask狀態,可以為RUNNING, FINISHED,PENDING ,只能在非FINISHED狀態取消
示例:
主執行緒中:
[程式碼]java程式碼:
01 02 03 04 05 06 07 08 09 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 |
|
AsyncTask執行過程
onPreExecute(),當任務執行之前開始呼叫此方法,可以不用實現。 doInBackground(Params…) 此方法在後臺執行緒執行,完成任務的主要工作,通常需要較長的時間。在執行過程中呼叫 publicProgress(Progress…)更新任務的進度。 onProgressUpdate(Progress…) 此方法在主執行緒執行,用於顯示任務執行的進度。 onPostExecute(Result) 此方法在主執行緒執行,任務執行的結果作為此方法的引數返回
當任務的狀態發生改變時(1、執行成功2、取消執行3、進度更新),工作執行緒會向UI執行緒的Handler傳遞訊息。Handler要處理其他執行緒傳遞過來的訊息。在AsyncTask中,InternalHandler是在UI執行緒上建立的,它接收來自工作執行緒的訊息,並呼叫相關的回撥函式。
AsyncTask的呼叫規則:
1.必須在UI執行緒中建立Task例項
2.必須在UI執行緒執行execute
3.不能手動呼叫onPreExecute()、onPostExecute、doInBackground、onProgressUpdate
4.只能呼叫一次execute,如果嘗試重複呼叫,則會丟擲異常( 當任務正在執行或者已經完成,會丟擲IllegalStateException)
AsyncTask總結:
1、 AsyncTask的本質是一個靜態的執行緒池,AsyncTask派生出的子類可以實現不同的非同步任務,這些任務都是提交到靜態的執行緒池中執行。
2、執行緒池中的工作執行緒執行doInBackground(mParams)方法去執行非同步任務
3、當任務狀態改變之後,工作執行緒會向UI執行緒傳送訊息,AsyncTask內部的InternalHandler接收這些訊息,並呼叫相關的回撥函式進行處理
Thread+handler 非UI執行緒更新介面
本質是子執行緒傳送訊息到UI執行緒,通知UI執行緒進行介面更新,由UI執行緒中的handler物件負責相應的處理。
需注意:不能直接在Thread中操作UI,如
[程式碼]java程式碼:
1 2 3 4 5 6 7 8 9 |
|
Android採用UI單執行緒模型,所以只能在主執行緒中對UI元素進行操作。如果在非UI執行緒直接對UI進行了操作,
報錯:CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views
此時,我們可以使用handler物件的post(Runnable)方法傳送一個Runnable物件到主執行緒中,Handler的handleMessage方法實際是由關聯有該訊息佇列的UI thread呼叫,因此,並不違反單執行緒模型
如:
[程式碼]java程式碼:
01 02 03 04 05 06 07 08 09 10 11 12 13 |
|
Thread : Thread.start()方法,開啟新的執行緒,當前執行緒(主執行緒)併發執行;run()方法會被新開啟的執行緒執行
Thread.run(),用於封裝執行緒執行的任務程式碼,直接用建立的執行緒物件呼叫,並沒有產生新的執行緒,在當前正在執行的執行緒(如,主執行緒)執行run方法
Handler:接收子執行緒傳送的物件,並負責處理該物件,用來更新介面,連線其他執行緒與主執行緒的橋樑,實現執行緒間通訊。提供非同步訊息處理機制,包含兩個佇列,一個是執行緒佇列,一個是訊息佇列。使用post方法將執行緒物件新增到執行緒佇列中,使用sendMessage(message)方法將訊息新增到訊息佇列中。
非UI執行緒傳送訊息到UI執行緒分為兩部:
子執行緒傳送訊息到UI執行緒的訊息佇列
處理傳送到UI執行緒的訊息,子類化handler,實現public void handleMessage (Message msg)方法
Handler中分發訊息的方法:(long物件為時間)
[程式碼]java程式碼:
01 02 03 04 05 06 07 08 09 10 11 12 13 |
|
以上post類方法傳送一個Runnable物件到主執行緒佇列中,sendMessage類方法, 傳送一個Message物件到佇列中,等待UI執行緒處理,
使用post方法將Runnable物件放到Handler的執行緒佇列中,該Runnable的執行其實並未單獨開啟執行緒,而是仍然在當前Activity的UI執行緒中執行,Handler只是呼叫了Runnable物件的run方法。
handler:預設執行在當前的Looper物件中,一個Looper只有在處理完一個message物件後,才會處理下一個,因此,如需併發處理,可考慮使用不同的Looper
message與runnable:
message是訊息,可以傳遞一些引數,Handler獲取這些資訊並做出處理,而Runnable則是直接給出處理的方法
停止執行緒:呼叫Handler物件的removeCallbacks(Runnable r)從執行緒佇列中移除執行緒物件,使執行緒停止執行
清除訊息:Handler物件的handler.removeMessages(what)/handler.removeMessages(what,object)
當我們不清楚在UI執行緒還是在其他執行緒執行的時候,可以使用runOnUiThread(action);//....
Thread+handler於AsyncTask
兩者的區別在於:
AsyncTask可以透過實現onPostExecute方法直接操作UI,該方法在UI執行緒呼叫,耗時操作在後臺執行緒doInBackground,不適合無限的迴圈
Thread.start(),開啟一個新的執行緒與UI執行緒並行,並不能直接操作UI(由於單執行緒模型的原因),因此,傳送handler物件的
message/runnable物件到訊息佇列/主執行緒佇列中,由handler接收訊息並進行處理,而runnable物件則直接進行處理
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4687/viewspace-2813698/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- AsyncTask 程式碼分析
- 磁碟原理簡要分析
- Android 原始碼分析之 AsyncTask 原始碼分析Android原始碼
- AsyncTask的理解與應用
- Multidex(分包)實現簡要分析IDE
- 夢想CMS(lmxcms)1.4 簡要分析
- Oracle RAC簡介與要點Oracle
- hashCode()方法原始碼執行簡要分析原始碼
- 雲伺服器與傳統伺服器的區別簡要分析伺服器
- 【原始碼解析】AsyncTask的用法與規則原始碼
- 簡要分析Hacking Team 遠端控制系統
- 理解 AsyncTask 原理
- 簡要MR與Spark在Shuffle區別Spark
- 對網易雲性格主導色實現與演算法的簡要分析演算法
- AsyncTask 面試解析面試
- Android AsyncTask 詳解Android
- AsyncTask原始碼解析原始碼
- AsyncTask實現原理
- DigiCert證書屬於什麼級別 簡要分析
- 簡要分析ZooKeeper基本原理及安裝部署
- redux簡單實現與分析Redux
- 軟體測評中心簡要分析:為什麼要進行軟體效能測試?
- Cmake簡要配置
- AsyncTask非同步任務類非同步
- Linux SNAT/DNAT簡單理解與案例分析。Linux
- SDRAM簡要歷史
- Android中非同步任務(AsyncTask)Android非同步
- AsyncTask你真的用對了嗎?
- 幣海旭日5.4:比特幣行情簡要分析和做單點位提示:比特幣
- CVE-2015-7547簡單分析與除錯除錯
- TotallySAF+Ubuntu簡要配置Ubuntu
- PHP 魔術常量簡要PHP
- 簡要理解CommonJS規範JS
- Android入門教程 | AsyncTask 使用介紹Android
- Android後臺任務(HandlerThread、AsyncTask、IntentService)AndroidthreadIntent
- Android 非同步載入——AsyncTask詳談Android非同步
- Android 多執行緒-----AsyncTask詳解Android執行緒
- 簡要分析近幾年商業軟體開發平臺的現狀