Android AsyncTask

簡介:

    AsyncTask是android提供的輕量級的異步類。比Handler更輕量級一些,適用於簡單的異步處理。android

    AsyncTask內部封裝了Thread和Handler,簡化Thread+Handler,可讓咱們在後臺進行計算而且把計算的結果及時更新到UI上。併發

    AsyncTask並非像多個線程那樣徹底並行執行的。異步

優缺點:

     優勢:ide

         簡單,快捷ui

         過程可控url

         結構清晰,功能定義明確spa

         對於多個後臺任務時,簡單,清晰.net

     缺點:線程

         在使用多個異步操做和並須要進行Ui變動時,就變得複雜起來.設計

         在單個後臺異步處理時,顯得代碼過多,結構過於複雜(相對性)

         AsyncTask中維護着一個長度爲128的線程池,同時能夠執行5個工做線程,還有一個緩衝隊列,當線程池中已有128個線程,緩衝隊列已滿時,若是此時向線程提交任務,將會拋出RejectedExecutionException。

         解決:由一個控制線程來處理AsyncTask的調用判斷線程池是否滿了,若是滿了則線程睡眠不然請求AsyncTask繼續處理。

 

構造方法:

    AsyncTask直接繼承於Object類,位置爲android.os.AsyncTask。要使用AsyncTask工做咱們要提供三個泛型參數,並重載幾個方法(至少重載一個)。

     AsyncTask定義了三種泛型類型 Params,Progress和Result。

     Params 啓動任務執行的輸入參數,好比HTTP請求的URL。

     Progress 後臺任務執行時,若是須要在界面上顯示當前的進度,則使用這裏指定的泛型做爲進度單位。

     Result 後臺執行任務最終返回的結果,好比String。

一個異步加載數據最少要重寫如下這兩個方法:

    doInBackground(Params…) 後臺執行,比較耗時的操做均可以放在這裏。注意這裏不能直接操做UI。此方法在後臺線程執行,完成任務的主要工做,一般須要較長的時間。在執行過程當中能夠調用publicProgress(Progress…)來更新任務的進度。

    onPostExecute(Result)  至關於Handler 處理UI的方式,在這裏面可使用在doInBackground 獲得的結果處理操做UI。 此方法在主線程執行,任務執行的結果做爲此方法的參數返回

有必要的話你還得重寫如下這三個方法,但不是必須的:

     onProgressUpdate(Progress…)   可使用進度條增長用戶體驗度。 此方法在主線程執行,用於顯示任務執行的進度。當在後臺任務中調用了publishProgress(Progress...)方法後,這個方法就很快會被調用,方法中攜帶的參數就是在後臺任務中傳遞過來的。

     onPreExecute()     這裏是最終用戶調用Excute時的接口,當任務執行以前開始調用此方法,能夠在這裏顯示進度對話框。

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

 

使用AsyncTask類,如下是幾條必須遵照的準則:

     AsyncTask的類必須在UI線程加載(從4.1開始系統會幫咱們自動完成)

     AsyncTask對象必須在UI線程建立

     execute方法必須在UI線程調用

     不要在你的程序中去直接調用onPreExecute(), onPostExecute, doInBackground, onProgressUpdate方法

     一個AsyncTask對象只能執行一次,即只能調用一次execute方法,不然會報運行時異常

    AsyncTask不是被設計爲處理耗時操做的,耗時上限爲幾秒鐘,若是要作長耗時操做,強烈建議你使用Executor,ThreadPoolExecutor以及FutureTask

    在1.6以前,AsyncTask是串行執行任務的,1.6的時候AsyncTask開始採用線程池裏處理並行任務,可是從3.0開始,爲了不AsyncTask所帶來的併發錯誤,AsyncTask又採用一個線程來串行執行任務

 

簡單實例:

public class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    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在3.0以上的系統中並行起來

    AsyncTask在4.1.1及是串行的,在2.3.3應該是並行的

@TargetApi(Build.VERSION_CODES.HONEYCOMB)  
@Override  
public void onClick(View v) {  
    if (v == mButton) {  
        new MyAsyncTask("AsyncTask#1").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");  
        new MyAsyncTask("AsyncTask#2").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");  
        new MyAsyncTask("AsyncTask#3").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");  
        new MyAsyncTask("AsyncTask#4").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");  
        new MyAsyncTask("AsyncTask#5").executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"");  
    }  
  
}  
  
private static class MyAsyncTask extends AsyncTask<String, Integer, String> {  
  
    private String mName = "AsyncTask";  
  
    public MyAsyncTask(String name) {  
        super();  
        mName = name;  
    }  
  
    @Override  
    protected String doInBackground(String... params) {  
        try {  
            Thread.sleep(3000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        return mName;  
    }  
  
    @Override  
    protected void onPostExecute(String result) {  
        super.onPostExecute(result);  
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        Log.e(TAG, result + "execute finish at " + df.format(new Date()));  
    }  
}

避免AsyncTask內存泄漏的簡單例子

相關文章
相關標籤/搜索