【Android】Android中的線程(AsyncTask)

以下內容部分摘自:
http://www.cnblogs.com/xiaoluo501395377/p/3430542.html

關於Android的知識詳見上方鏈接,其中特別要注意的是,由於線程不安全的,所以不能在主線程(UI Thread)之外的線程當中對UI控件進行操作。因此在Android的多線程編程當中,有2條非常重要的原則必須要遵守:
  • 絕對不能在UI Thread當中進行耗時的操作阻塞UI Thread
  • 不能在UI Thread之外的線程當中操縱UI元素
Android中有兩種方式實現線程:一是AsyncTask,一是Thread+Handler。這篇文章先總結AsyncTask,之後再總結Thread+Handler+,博主更推薦用AsyncTask,具體原因在總結了Thread+Handler之後會對比說明。

AsyncTask
要掌握AsyncTask,必須瞭解3個泛型和4個步驟。首先看看AsyncTask這個抽象類的定義,定義一個類來繼承AsyncTask時,需要爲其指定3個泛型參數:AsyncTask<Params, Progress, Result>
  • Params:這個泛型指定的是我們傳遞給異步任務執行時的參數的類型
  • Progress:這個泛型指定的是我們的異步任務在執行的時候將執行的進度返回給UI線程的參數的類型
  • Result:這個泛型指定的異步任務執行完後返回給UI線程的結果的類型

在定義一個類繼承AsyncTask類的時候,必須要指定好這三個泛型的類型,如果都不指定的話,則都將其寫成void:AsyncTask<void, void, void>。

執行一個AsyncTask異步任務是按照下面的4個步驟分別執行的:

  • onPreExecute():在執行異步任務之前的時候執行,並且是在UI Thread當中執行的。通常在這個方法裏,做一些UI控件的初始化的操作,例如彈出ProgressDialog。
  • doInBackground(Params... params):在onPreExecute方法執行完之後,馬上執行這個方法,這個方法就是處理異步任務的方法。Android操作系統會在後臺的線程池當中開啓一個Worker Thread來執行,執行完之後就可以將執行結果發送給最後一個 onPostExecute方法。通常在這個方法裏,做一些從網絡當中獲取數據等耗時操作。
  • onProgressUpdate(Progess... values):這個方法也是在UI Thread當中執行的,有時候需要將執行的進度返回給UI界面,例如下載一張網絡圖片,需要時刻顯示其下載的進度,就可以使用這個方法來更新我們的進度。這個方法在調用之前,我們需要在 doInBackground 方法中調用publishProgress(Progress) 方法來將進度時時刻刻傳遞給 onProgressUpdate方法更新。
  • onPostExecute(Result... result):異步任務執行完之後,會將結果返回給這個方法,這個方法也是在UI Thread當中調用的,可以將返回的結果顯示在UI控件上。

有的時候只有一個 doInBackground 的抽象方法,其他三個方法都沒有實現。這是因爲如果要做一個異步任務,必須得爲其開闢一個新的Thread,讓其完成一些操作,而在完成這個異步任務時,可能並不需要不需要隨時更新我的ProgressDialog的進度條,也並不需要將結果更新給UI界面,所以除了 doInBackground 方法之外的三個方法,都不是必須有的,必須要實現的方法是 doInBackground 方法


使用AsyncTask時的其他有關知識
1. 關閉AsyncTask異步任務

通過調用 cancel(boolean)方法,可以在任何時刻來取消異步任務的執行,調用完這個方法後系統會隨後調用 isCancelled() 方法並且返回true。如果調用了這個方法,那麼在 doInBackgroud() 方法執行完之後,就不會調用 onPostExecute() 方法了,取而代之的是調用 onCancelled() 方法。如果有必要的話,爲了確保Task已經被取消了,我們需要經常調用 isCancelled() 方法來判斷。

在java的線程中,沒有辦法停止一個正在運行中的線程。在Android的AsyncTask中也是一樣如果必須要停止一個線程,可以採用這個線程中設置一個標誌位,在doInBackground()方法中的關鍵步驟判斷這個標誌位以決定是否繼續執行(對於Thread+Handler就在run()中判斷標誌位),然後在需要終止此線程的地方改變這個標誌位以達到停止線程的目的。這只是一種辦法,在android 如何結束一個線程?這篇文章裏有更好的辦法,博主沒有用到,先mark一下~

2. 必須要遵循的原則

  • AsyncTask的對象必須在UI Thread當中實例化,execute方法必須在UI Thread當中調用。
  • 不要手動調用AsyncTask的onPreExecute、doInBackground、onProgressUpdate、onPostExecute,這些方法都是由Android系統自動調用的。
  • AsyncTask任務只能被執行一次。
下面以博主最近自己在寫的一個程序爲例,po一下使用AsyncTask的代碼,博主的代碼中實現了onPreExecute、doInBackground、onPostExecute三種方法,在文章最上方的鏈接裏給出了實現onProgressUpdate的例子。

=====================================華麗麗的分割線===================================

功能描述:

博主最近在寫的App中,某個Activity需要解析xml文件,並將解析結果展示在界面上,解析xml的工作比較耗時,需要在Worker Thread中執行。

具體分析:
  • onPreExecute():將界面上“加載更多”按鈕的文字修改爲“正在加載,請稍後...”。
  • doInBackground(Params... params):解析xml文件,解析出的數據保存在一個List中,該List通過一個SimpleAdapter與UI組件聯繫在一起。
  • onPostExecute(Result... result):根據解析是否成功,在界面上給出提示信息;通過SimpleAdapter通知UI組件修改內容,以展示解析結果;恢復“加載更多”按鈕的文字。

根據以上分析,在Activity中增加一個繼承AsyncTask的類。

/**
 * 解析xml文件
 */
private class LoadPaperAsyncTask extends AsyncTask

要使用這個類先要在Activity中聲明一個變量

private LoadPaperAsyncTask asyncTask;

根據上面說到的“AsyncTask任務只能被執行一次”原則,每次需要解析xml文件時,博主都會將asyncTask重新new一下,例如:

asyncTask=new LoadPaperAsyncTask(auth+".xml");
asyncTask.execute(numOfPaper,true);

其中,execute的參數要與doInBackground中統一,在上面的代碼中規定params[0]爲int型,表示解析的起始序號,params[1]爲boolean型,表示是否是第一次解析,這裏execute與doInBackground統一了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章