AsyncTask異步任務的基本使用和注意事項

1、概述

AsyncTask是一種輕量級的異步任務類,屬於抽象類,使用時需實現子類和相關方法。它能夠在線程池中執行後臺任務,而後把執行的進度和最終結果傳遞給主線程並在主線程中更新UI,經過AsyncTask能夠更加方便執行後臺任務以及在主線程中操做UI,能夠輕鬆解決多線程之間的通訊問題,可是AsyncTask並不適合進行特別耗時的後臺任務,對於特別耗時的任務來講,建議使用線程池。java

2、做用

  1. 實現多線程:在工做線程中執行任務,如耗時任務。緩存

  2. 異步通訊、消息傳遞:實現工做線程&主線程(UI線程)之間的通訊,即:將工做線程的執行結果傳遞給主線程,從而在主線程中執行相關的UI操做,最終保證線程安全。安全

3、優勢

  1. 方便實現異步通訊:不需使用 「任務線程(如繼承Thread類)+ Handler」的複雜組合。bash

  2. 節省資源:採用線程池的緩存線程 + 複用線程,避免了頻繁建立&銷燬線程所帶來的系統資源開銷。網絡

4、核心方法

要掌握AsyncTask,就要掌握三個參數和四個步驟。多線程

一、三個參數

AsyncTask<Params, Progress, Result>
複製代碼

Params:表示異步任務執行時的參數類型,該參數會傳給AysncTask的doInBackground()方法異步

Progress:表示異步任務的執行進度的參數類型,該參數會做爲onProgressUpdate()方法的參數ide

Result:表示異步任務的返回結果的參數類型,該參數會做爲onPostExecute()方法的參數源碼分析

在定義一個類繼承AsyncTask類的時候,必須指定好這三個泛型的類型,若是都不指定的話,則都將其寫成Void,例如:spa

AsyncTask <Void, Void, Void>
複製代碼

二、四個步驟

當執行一個異步任務時,須要按照下面的4個步驟分別執行:

onPreExecute():這個方法是在執行異步任務以前的時候執行,而且是在UI Thread當中執行的, 一般咱們在這個方法裏作一些UI控件的初始化的操做,例如彈出ProgressDialog。

doInBackground(Params...params):在onPreExecute()方法執行完後,會立刻執行這個方法,這個方法就是來處理異步任務的方法,Android操做系統會在後臺的線程池當中開啓一個worker thread來執行 這個方法(即在worker thread當中執行),執行完後將執行結果發送給最後一個onPostExecute方法,在這個方法裏,咱們能夠從網絡當中獲取數據等一些耗時的操做。

onProgressUpdate(Progess...values):這個方法也是在UIThread當中執行的,在異步任務執行的時候,有時須要將執行的進度返回給UI界面,例以下載一張網絡圖片,咱們須要時刻顯示其下載的進度,就可使用這個方法來更新進度。這個方法在調用以前,咱們須要在doInBackground方法中調用一個 publishProgress(Progress) 的方法來將進度時時刻刻傳遞給onProgressUpdate方法來更新。

onPostExecute(Result...result):當異步任務執行完以後,就會將結果返回給這個方法,這個方法也是在UI Thread當中調用的,咱們能夠將返回的結果顯示在UI控件上。

三、額外補充doInBackground和onCancelled

(1)爲何AsyncTask抽象類只有一個doInBackground的抽象方法呢?

若是要作一個異步任務,咱們必需要爲其開闢一個新的Thread,讓其完成一些操做,而在完成這個異步任務時,可能並不須要彈出ProgressDialog,並不須要隨時更新ProgressDialog的進度條,也並不須要將結果更新給UI界面,因此除了doInBackground方法以外的三個方法,都不是必須有的,所以必需要實現的方法是doInBackground方法。

(2)Cancel a Task-取消異步任務

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

5、基本使用

AsyncTask的使用步驟分爲兩步:

  • 第一步:建立AsyncTask子類 & 根據需求實現核心方法
  • 第二步:建立AsyncTask子類的實例對象,手動調用execute()執行異步線程任務
第一步:建立AsyncTask子類
    一、繼承AsyncTask類
    二、爲3個泛型參數指定類型;若不使用,可用java.lang.Void類型代替
    三、根據需求,在AsyncTask子類內實現核心方法

  private class MyTask extends AsyncTask<Params, Progress, Result> {
  
     //執行線程任務前的操做
      @Override
      protected void onPreExecute() {
           ...
        }

      //接收輸入參數、執行任務中的耗時操做、返回線程任務執行的結果
      @Override
      protected String doInBackground(String... params) {
            //自定義的線程任務
            HttpClient httpClient = new DefaultHttpClient() ;
            ....
            
            //可調用publishProgress()顯示進度, 以後將執行onProgressUpdate()
             publishProgress(count);
         }

      //在主線程 顯示線程任務執行的進度
      @Override
      protected void onProgressUpdate(Integer... progresses) {
            ...
        }

      //接收線程任務執行結果、將執行結果顯示到UI組件
      @Override
      protected void onPostExecute(String result) {
             // UI操做
             .....
        }

      //將異步任務設置爲:取消狀態
      @Override
        protected void onCancelled() {
             ...
        }
  }

複製代碼
第二步:建立AsyncTask子類的實例對象,手動調用execute(Params... params) 從而執行異步線程任務
 MyTask mTask = new MyTask();
 mTask.execute();
 
複製代碼

6、使用時注意事項

一、使用AsyncTask遵循的原則

(1)AsyncTask子類的實例必須在UI線程中建立

(2)execute方法必須在UI線程中調用

(3)同一個AsyncTask實例對象只能執行1次,若執行第2次將會拋出異常

(4)執行任務中,系統會自動調用AsyncTask的一系列方法:onPreExecute()、doInBackground()、onProgressUpdate() 、 onPostExecute() 不能手動調用這些方法

二、AsyncTask引發的內存泄漏

緣由:非靜態內部類持有外部類的匿名引用,致使Activity沒法釋放

解決: AsyncTask內部持有外部Activity的弱引用 & AsyncTask改成靜態內部類 & 在Activity銷燬以前,AsyncTask.cancel()取消運行,以此來保證程序的穩定

7、總結

本文介紹了AysncTask的基本使用和使用過程當中注意事項,包括遵照原則和內存泄漏。稍後會分析AysncTask的工做原理,包括多任務時AysncTask採用的是串行or並行以及源碼分析。

相關文章
相關標籤/搜索