Android異步任務機制之AsycTask


在Android中實現異步任務機制有兩種方式,Handler和AsyncTask。 

本篇就說說AsyncTask的異步實現。

1、什么時候使用 AsnyncTask

     在上一篇文章已經說了,主線程主要負責控制UI頁面的顯示、更新、交互等。 為了有更好的用戶體驗,UI線程中的操作要求越短越好。

     我們把耗時的操作(例如網絡請求、數據庫操作、復雜計算)放到單獨的子線程中操作,以避免主線程的阻塞。但是在子線程中不能更新UI界面,這時候需要使用handler。

     但如果耗時的操作太多,那么我們需要開啟太多的子線程,這就會給系統帶來巨大的負擔,隨之也會帶來性能方面的問題。在這種情況下我們就可以考慮使用類AsyncTask來異步執行任務,不需要子線程和handler,就可以完成異步操作和刷新UI。

     不要隨意使用AsyncTask,除非你必須要與UI線程交互.默認情況下使用Thread即可,要注意需要將線程優先級調低.AsyncTask適合處理短時間的操作,長時間的操作,比如下載一個很大的視頻,這就需要你使用自己的線程來下載,不管是斷點下載還是其它的.

 

2、AsnyncTask原理

  AsyncTask主要有二個部分:一個是與主線程的交互,另一個就是線程的管理調度。雖然可能多個AsyncTask的子類的實例,但是AsyncTask的內部Handler和ThreadPoolExecutor都是進程范圍內共享的,其都是static的,也即屬於類的,類的屬性的作用范圍是CLASSPATH,因為一個進程一個VM,所以是AsyncTask控制着進程范圍內所有的子類實例。 

  AsyncTask內部會創建一個進程作用域的線程池來管理要運行的任務,也就就是說當你調用了AsyncTask的execute()方法后,AsyncTask會把任務交給線程池,由線程池來管理創建Thread和運行Therad。

 

3、AsyncTask介紹

  Android的AsyncTask比Handler更輕量級一些(只是代碼上輕量一些,而實際上要比handler更耗資源),適用於簡單的異步處理。
  
  Android之所以有Handler和AsyncTask,都是為了不阻塞主線程(UI線程),因為UI的更新只能在主線程中完成,因此異步處理是不可避免的。

  AsyncTask:對線程間的通訊做了包裝,是后台線程和UI線程可以簡易通訊:后台線程執行異步任務,將result告知UI線程。

使用AsyncTask分為兩步: 

① 繼承AsyncTask類實現自己的類

public abstract class AsyncTask<Params, Progress, Result> {
Params: 輸入參數,對應excute()方法中傳遞的參數。如果不需要傳遞參數,則直接設為void即可。

Progress:后台任務執行的百分比

Result:返回值類型,和doInBackground()方法的返回值類型保持一致。

 

②復寫方法

最少要重寫以下這兩個方法:

    • doInBackground(Params…)

        在子線程(其他方法都在主線程執行)中執行比較耗時的操作,不能更新UI,可以在該方法中調用publishProgress(Progress…)來更新任務的進度。Progress方法是AsycTask中一個final方法只能調用不能重寫。

    • onPostExecute(Result)

        使用在doInBackground 得到的結果處理操作UI, 在主線程執行,任務執行的結果作為此方法的參數返回。
        
      有時根據需求還要實現以下三個方法:

    • onProgressUpdate(Progress…)

        可以使用進度條增加用戶體驗度。 此方法在主線程執行,用於顯示任務執行的進度。

    • onPreExecute()

        這里是最終用戶調用Excute時的接口,當任務執行之前開始調用此方法,可以在這里顯示進度對話框。

    • onCancelled()

        用戶調用取消時,要做的操作

4、AsyncTask示例

按照上面的步驟定義自己的異步類:

public class MyTask extends AsyncTask<String, Integer, String> {  
    //執行的第一個方法用於在執行后台任務前做一些UI操作  
    @Override  
    protected void onPreExecute() {  

    }  

    //第二個執行方法,在onPreExecute()后執行,用於后台任務,不可在此方法內修改UI
    @Override  
    protected String doInBackground(String... params) {  
         //處理耗時操作
        return "后台任務執行完畢";  
    }  

   /*這個函數在doInBackground調用publishProgress(int i)時觸發,雖然調用時只有一個參數  
    但是這里取到的是一個數組,所以要用progesss[0]來取值  
    第n個參數就用progress[n]來取值   */
    @Override  
    protected void onProgressUpdate(Integer... progresses) {  
        //"loading..." + progresses[0] + "%"
        super.onProgressUpdate(progress);  
    }  

    /*doInBackground返回時觸發,換句話說,就是doInBackground執行完后觸發  
    這里的result就是上面doInBackground執行后的返回值,所以這里是"后台任務執行完畢"  */
    @Override  
    protected void onPostExecute(String result) { 

    }  

    //onCancelled方法用於在取消執行中的任務時更改UI  
    @Override  
    protected void onCancelled() {  

    }  
}

在主線程申明該類的對象,調用對象的execute()函數開始執行。

MyTask t= new MyTask();
t.execute();//這里沒有參數

 

5、使用AsyncTask需要注意的地方

  • AsnycTask內部的Handler需要和主線程交互,所以AsyncTask的實例必須在UI線程中創建

  • AsyncTaskResult的doInBackground(mParams)方法執行異步任務運行在子線程中,其他方法運行在主線程中,可以操作UI組件。

  • 一個AsyncTask任務只能被執行一次。

  • 運行中可以隨時調用AsnycTask對象的cancel(boolean)方法取消任務,如果成功,調用isCancelled()會返回true,並且不會執行 onPostExecute() 方法了,而是執行 onCancelled() 方法。

  • 對於想要立即開始執行的異步任務,要么直接使用Thread,要么單獨創建線程池提供給AsyncTask。默認的AsyncTask不一定會立即執行你的任務,除非你提供給他一個單獨的線程池。如果不與主線程交互,直接創建一個Thread就可以了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM