第六課:Android的異步任務(AsyncTask)

Android 提供了一套專門用於異步處理的類。即:AsyncTask 類。使用這個類可以爲耗時程序開闢一個新線程進行處理,處理完時返回。


AsyncTask<Params, Progress, Result> 是一個抽象類,通常用於被集成。集成 AsyncTask 時需要制定如下三個泛型參數(傳遞的數據都是對應類型的數組,數組都是可變長的

Params:啓動任務執行的輸入參數的類型。對應 execute() doInBackground() 的傳遞類型。

Progress:後臺任務完成的進度值的類型。對應 publishProgress()  向 progressUpdate() 傳遞的類型。

Result:後臺執行任務完成後返回結果的類型。對應doInBackground()的返回類型和傳遞給 onPostExecute() 的類型


AsyncTask 類主要用到的幾個內部回調函數有以下四個,可以根據需要重寫,其中 doInBackGround(Params...) 必須重寫:

onPreExecute():該方法將在執行實際的後臺操作前被UI thread調用。可以在該方法中做一些準備工作,如在界面上顯示一個進度條。

doInBackGround(Params... params):將在onPreExecute 方法執行後馬上執行,該方法運行在後臺線程中。這裏將主要負責執行那些很耗時的後臺計算工作。可以調用 

publishProgress(Progress... values) 方法來更新實時的任務進度。該方法是抽象方法,子類必須實現

onProgressUpdate(Progress... values):在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。

onPostExecute(Result result):在doInBackground 執行完成後,onPostExecute 方法將被UI thread調用,後臺的計算結果將通過該方法傳遞到UI thread。


回調邏輯關係如下:


回調邏輯關係說明:

1.主線程調用AsynTask子類實例的 execute(Params... params 方法後,首先會調用 onPreExecute() 方法。onPreExecute() 在主線程中運行,可以用來寫一些開始提示代碼或者進度條等。

2.之後啓動新線程,調用 doInBackground(Params... params ) 方法,進行異步數據處理。

3.處理完畢之後異步線程結束,在主線程中調用 onPostExecute(Result result) 方法。onPostExecute(Result result)  可以進行一些結束提示處理。


使用 AsyncTask 只需要如下三步即可:

1.創建 AsyncTask 的子類,併爲三個泛型參數指定類型。如果某個泛型參數不需要指定類型,則可將它指定爲Void。

2.根據需要,實現 AsyncTask 的方法。

3.調用 AsyncTask 子類的實例的 execute(Params...)開始執行 AsyncTask 任務。


爲了正確的使用AsyncTask類,必須遵守以下是幾條準則:

1.必須在UI thread 中創建 AsyncTask 的實例。

2.必須在UI thread 中調用 AsyncTask 的實例的 execute() 方法。

3. AsyncTask 的 onPreExecute()、onPostExecute(Result result)、doInBackground(Params... params)、onProgressUpdate(Progress... values)這幾個方法不該由程序員來調用,而是由 Android 系統負責調用。

4.每個 AsyncTask 只能被執行一次,多次調用時將會出現異常


例1:使用異步任務下載

public class AsyncTaskTest extends Activity
{
	private TextView show;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		show = (TextView) findViewById(R.id.show);
	}

	// 重寫該方法,爲界面的按鈕提供事件響應方法
	public void download(View source) throws MalformedURLException
	{
		DownTask task = new DownTask(this);
		task.execute(new URL("http://www.crazyit.org/ethos.php"));
	}

	class DownTask extends AsyncTask<URL, Integer, String>
	{
		// 可變長的輸入參數,與AsyncTask.exucute()對應
		ProgressDialog pdialog;
		// 定義記錄已經讀取行的數量
		int hasRead = 0;
		Context mContext;

		public DownTask(Context ctx)
		{
			mContext = ctx;
		}

		@Override
		protected String doInBackground(URL... params)
		{
			StringBuilder sb = new StringBuilder();
			try
			{
				URLConnection conn = params[0].openConnection();
				// 打開conn連接對應的輸入流,並將它包裝成BufferedReader
				BufferedReader br = new BufferedReader(
					new InputStreamReader(conn.getInputStream()
					, "utf-8"));
				String line = null;
				while ((line = br.readLine()) != null)
				{
					sb.append(line + "\n");
					hasRead++;
					publishProgress(hasRead);
				}
				return sb.toString();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(String result)
		{
			// 返回HTML頁面的內容
			show.setText(result);
			pdialog.dismiss();
		}

		@Override
		protected void onPreExecute()
		{
			pdialog = new ProgressDialog(mContext);
			// 設置對話框的標題
			pdialog.setTitle("任務正在執行中");
			// 設置對話框 顯示的內容
			pdialog.setMessage("任務正在執行中,敬請等待...");
			// 設置對話框不能用“取消”按鈕關閉
			pdialog.setCancelable(false);
			// 設置該進度條的最大進度值
			pdialog.setMax(202);
			// 設置對話框的進度條風格
			pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			// 設置對話框的進度條是否顯示進度
			pdialog.setIndeterminate(false);
			pdialog.show();
		}

		@Override
		protected void onProgressUpdate(Integer... values)
		{
			// 更新進度
			show.setText("已經讀取了【" + values[0] + "】行!");
			pdialog.setProgress(values[0]);
		}
	}
}



源代碼下載

發佈了34 篇原創文章 · 獲贊 32 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章