天天看點

使用AsyncTask異步更新UI界面及原理分析

概述: AsyncTask是在Android SDK 1.5之後推出的一個友善編寫背景線程與UI線程互動的輔助類。AsyncTask的内部實作是一個線程池,所有送出的異步任務都會在這個線程池中的工作線程内執行,當工作線程需要跟UI線程互動時,工作線程會通過向在UI線程建立的Handler傳遞消息的方式,調用相關的回調函數,進而實作UI界面的更新。

AsyncTask抽象出背景線程運作的五個狀态,分别是:1、準備運作,2、正在背景運作,3、進度更新,4、完成背景任務,5、取消任務,對于這五個階段,AsyncTask提供了五個回調函數:

1、準備運作:onPreExecute(),該回調函數在任務被執行之後立即由UI線程調用。這個步驟通常用來建立任務,在使用者接口(UI)上顯示進度條。

2、正在背景運作:doInBackground(Params...),該回調函數由背景線程在onPreExecute()方法執行結束後立即調用。通常在這裡執行耗時的背景計算。計算的結果必須由該函數傳回,并被傳遞到onPostExecute()中。在該函數内也可以使用publishProgress(Progress...)來釋出一個或多個進度機關(unitsof progress)。這些值将會在onProgressUpdate(Progress...)中被釋出到UI線程。

3. 進度更新:onProgressUpdate(Progress...),該函數由UI線程在publishProgress(Progress...)方法調用完後被調用。一般用于動态地顯示一個進度條。

4. 完成背景任務:onPostExecute(Result),當背景計算結束後調用。背景計算的結果會被作為參數傳遞給這一函數。

5、取消任務:onCancelled (),在調用AsyncTask的cancel()方法時調用

AsyncTask的構造函數有三個模闆參數:

1.Params,傳遞給背景任務的參數類型。

2.Progress,背景計算執行過程中,進步機關(progress units)的類型。(就是背景程式已經執行了百分之幾了。)

3.Result, 背景執行傳回的結果的類型。

AsyncTask并不總是需要使用上面的全部3種類型。辨別不使用的類型很簡單,隻需要使用Void類型即可。

例子:從網絡上下載下傳圖檔,下載下傳完成後在UI界面上顯示出來,并會模拟下載下傳進度更新。

AsyncTaskActivity.java

Activity布局檔案main.xml

記得在AndroidManifest.xml加入相關權限

<uses-permission android:name="android.permission.INTERNET"/>

運作結果: 

<a href="http://blog.92coding.com/wp-content/uploads/2012/03/AsyncTaskDemo.jpg"></a>

AsyncTask的實作原理

在分析實作流程之前,我們先了解一下AsyncTask有哪些成員變量

當點選“下載下傳圖檔”按鈕之後會建立一個GetImageTask對象:

GetImageTask task = new GetImageTask();

此時會調用父類AsyncTask的構造函數:

AsyncTask.java

WorkerRunnable類實作了callable接口的call()方法,該函數會調用我們在AsyncTask子類中實作的doInBackground(mParams)方法,由此可見,WorkerRunnable封裝了我們要執行的異步任務。FutureTask中的protected void done() {}方法實作了異步任務狀态改變後的操作。當異步任務被取消,會向UI線程傳遞MESSAGE_POST_CANCEL消息,當任務成功執行,會向UI線程傳遞MESSAGE_POST_RESULT消息,并把執行結果傳遞到UI線程。 由此可知,AsyncTask在構造的時候已經定義好要異步執行的方法doInBackground(mParams)和任務狀态變化後的操作(包括失敗和成功)。 當建立完GetImageTask對象後,執行

<code>1</code>

此時會調用AsyncTask的execute(Params...params)方法 AsyncTask.java

當任務正在執行或者已經完成,會抛出IllegalStateException,由此可知我們不能夠重複調用execute(Params...params)方法。在送出任務到線程池之前,調用了onPreExecute()方法。然後才執行sExecutor.execute(mFuture)是任務送出到線程池。

前面我們說到,當任務的狀态發生改變時(1、執行成功2、取消執行3、進度更新),工作線程會向UI線程的Handler傳遞消息,Handler要處理其他線程傳遞過來的消息。在AsyncTask中,InternalHandler是在UI線程上建立的,它接收來自工作線程的消息,實作代碼如下:

當接收到消息之後,AsyncTask會調用自身相應的回調方法。

總結:1、 AsyncTask的本質是一個靜态的線程池,AsyncTask派生出的子類可以實作不同的異步任務,這些任務都是送出到靜态的線程池中執行。 2、線程池中的工作線程執行doInBackground(mParams)方法執行異步任務 3、當任務狀态改變之後,工作線程會向UI線程發送消息,AsyncTask内部的InternalHandler響應這些消息,并調用相關的回調函數

繼續閱讀