AsyncTask
,相信你們已經很熟悉了。它的內部封裝了Thread
和Handler
,這讓咱們能夠將一些耗時操做放到AsyncTask
,而且能將結果及時更新到UI上。AsyncTask
主要用於短期耗時操做,長時間耗時操做不建議使用AsyncTask
。下面經過Google官方的一個例子來認識AsyncTask
的用法。併發
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected void onPreExecute() { showProgress(); } protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); // Escape early if cancel() is called if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }
AsyncTask
是一個抽象類,咱們要使用時必須自定義一個類繼承於它。AsyncTask
的原型爲:ide
public abstract class AsyncTask<Params, Progress, Result> { }
它接收三個泛型參數,分別表示參數類型、進度類型、結果類型。測試
上述的例子中DownloadFilesTask
接收參數類型爲URL
類型,使用Integer
類型表示任務進度,最終的任務結果是一個Long
類型。this
注意:上面三個泛型類型不必定都得用一個明確的類型,對於沒有使用的類型,可使用
Void
類型代替。url
繼承AsyncTask
至少須要重寫doInBackground
方法,同時AsyncTask
也提供了另外三個方法供咱們重寫,分別是onPreExecute
、onProgressUpdate
、onPostExecute
。線程
publishProgress
方法被調用後執行,它運行在UI線程中。一般用於展現整個任務的一個進度。doInBackground
的返回結果會透傳給onPostExecute
的參數值,它運行在主線程中。一般咱們從這裏獲取任務執行完成後的結果數據。AsyncTask
類必須在UI線程加載。(在4.1系統版本以上會自動完成)AsyncTask
對象必須在UI線程建立,也就是說AsyncTask
的構造方法必須在UI線程中調用。(通過測試AsyncTask
對象能夠在子線程建立,只要保證execute
方法在UI線程執行就OK的。可是沒有人會這樣作,由於畫蛇添足!!!)execute
方法必須在UI線程中調用。這樣作是保證onPreExecute
方法運行在UI線程。onPreExecute
、doInBackground
、onProgressUpdate
、onProgressUpdate
方法。在AsyncTask
誕生之初,任務是在一個後臺線程中順序執行的。從Android 1.6開始,就變成了能夠在後臺線程中並行執行任務。而後,到了Android 3.0版本,又改爲了單線程順序執行,以此避免併發任務產生的錯誤行爲。code
爲了驗證上述結論,下面看一個Demo例子。orm
public class MainActivity extends Activity { public static final String TAG = "MyApplication"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new MyTask("task1").execute(); new MyTask("task2").execute(); new MyTask("task3").execute(); new MyTask("task4").execute(); new MyTask("task5").execute(); new MyTask("task6").execute(); } private class MyTask extends AsyncTask<Void, Void, Void> { private String taskName; MyTask(String taskName) { this.taskName = taskName; } @Override protected Void doInBackground(Void... integers) { try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Log.e(TAG, taskName + " finish at: " + df.format(new Date())); } } }
這個例子比較簡單,就是在MainActivity
啓動時,執行了六次MyTask
,並將任務執行後的時間節點打印出來。對象
手機的系統版本是Android 8.0,從上面的Log信息能夠看出,AsyncTask
的確是串行執行的。因爲現有測試機最低系統版本都是Android 4.1,已經很難找到Android 3.0如下的老古董機子了blog