AsyncTask 異步任務

參考瘋狂Android講義3.6章:


AsyncTask<Params,Progress,Result> 抽象類,三個泛型參數:

Params:啓動任務執行的輸入參數類型;

Progress:後臺任務完成的進度值的類型;

Result:後臺任務執行後返回的結果類型;

不需要指定類型的話用Void。


必須要繼承重寫的方法是:

doInBackground(Params... param):後臺線程要完成的任務;可以在該方法中調用publishProgress(Progress... values)方法更新任務執行的進度。


下邊例子還用到的方法:

onProgressUpdate(Progress... values):如果在doInBackground方法中調用publishProgress方法,則會觸發該方法;

onPreExecute():在執行後臺任務之前調用該方法,通常執行一些初始化工作,如在界面上顯示進度條;

onPostExecute(Result result):doInBackground方法執行完後將執行該方法,並將返回值作爲參數傳入該方法;


調用AsyncTask對象時,必須在UI線程中實例化對象,然後執行execute方法,開始後臺任務。


注意事項:

上邊提到的4個方法,都應該由Android系統負責調用。程序員只能調用實例對象的execute方法。

另外execute方法只能被執行一次,多次調用會報錯:

E/AndroidRuntime(3226): Caused by: java.lang.IllegalStateException: Cannot execute task: the task is already running.




crazy Android 給的示例:

package org.crazyit.handler;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.view.View;
import android.widget.TextView;

/**
 * Description: <br/>
 * site: <a href="http://www.crazyit.org">crazyit.org</a> <br/>
 * Copyright (C), 2001-2014, Yeeku.H.Lee <br/>
 * This program is protected by copyright laws. <br/>
 * Program Name: <br/>
 * Date:
 * @author Yeeku.H.Lee [email protected]
 * @version 1.0
 */
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.so.cn"));
	}

	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(true);
			// 設置該進度條的最大進度值
			pdialog.setMax(100);
			// 設置對話框的進度條風格
			pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			// 設置對話框的進度條是否顯示進度
			pdialog.setIndeterminate(true);
			pdialog.show();
		}

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

值得注意的是AndroidManifest.xml文件中需要加上訪問Internet URL的權限:

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





More about AsyncTask:

Android3.0之前,異步任務的線程池介紹:

http://www.linuxidc.com/Linux/2011-09/43150.htm

1、線程池中的工作線程少於5個時,將會創建新的工作線程執行異步任務

2、線程池中已經有5個線程,緩衝隊列未滿,異步任務將會放到緩衝隊列中等待

3、線程池中已經有5個線程,緩衝隊列已滿,那麼線程池將新開工作線程執行異步任務

4、線程池中已經有128個線程,緩衝隊列已滿,如果此時向線程提交任務,將會拋出RejectedExecutionException


5個以內的線程可以同步進行,6-15會放入緩衝隊列,16-128以上會新開啓新的工作線程。128以上會拋出異常。


3.0之後的異步任務線程池添加了新增了接口#executeOnExecutor(),可以自定義線程池。新增了二個預定義的線程池SERIAL_EXECUTORTHREAD_POOL_EXECUTOR

1、executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)就跟2.3版本的AsyncTask.execute()效果是一樣的

2、默認AsyncTask.execute()會一個接一個任務進行,不會同時進行,也就SERIAL_EXECUTOR

3、如果你想讓所有的任務都能併發同時運行,那就創建一個沒有限制的線程池(Executors.newCachedThreadPool())

http://blog.csdn.net/hitlion2008/article/details/7983449

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章