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 程式碼分析
- 磁碟原理簡要分析
- Android AsyncTask簡單用法Android
- Android Hal層簡要分析Android
- Access Animation破解的簡要分析
- Android的AsyncTask原始碼分析Android原始碼
- Architecture(1)AsyncTask原始碼分析原始碼
- cookie與session原理簡要CookieSession
- AsyncTask的理解與應用
- Android 原始碼分析之 AsyncTask 原始碼分析Android原始碼
- Multidex(分包)實現簡要分析IDE
- spycop5.5簡要註冊分析
- 夢想CMS(lmxcms)1.4 簡要分析
- Oracle RAC簡介與要點Oracle
- 原始碼分析 —— AsyncTask 完全解析(基於7.0)原始碼
- 雲伺服器與傳統伺服器的區別簡要分析伺服器
- 從原始碼角度一步步分析AsyncTask的用法與原理原始碼
- hashCode()方法原始碼執行簡要分析原始碼
- linux程式管理子系統簡要分析Linux
- 對網易雲性格主導色實現與演算法的簡要分析演算法
- Android AsyncTask運作原理和原始碼分析Android原始碼
- 簡要MR與Spark在Shuffle區別Spark
- 簡單演算法---A Speeder V2.5破解的簡要分析!演算法
- 【原始碼解析】AsyncTask的用法與規則原始碼
- 簡要分析Hacking Team 遠端控制系統
- 圖靈4本新書版式的簡要分析圖靈新書
- ORACLE關於執行計劃的簡要分析Oracle
- 影像處理軟體XFader的簡要分析
- Android開發AsyncTask原始碼分析【模板方法模式】Android原始碼模式
- 簡要分析ZooKeeper基本原理及安裝部署
- 簡要分析Android手機為啥不好用?Android
- 理解 AsyncTask 原理
- AsyncTask 面試解析面試
- 深入解析AsyncTask
- redux簡單實現與分析Redux
- android程式與執行緒詳解三:AsyncTaskAndroid執行緒