Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 多線程開發(三)-AnsycTask用法與解惑

多線程開發(三)-AnsycTask用法與解惑

編輯:關於Android編程

第5節 AsyncTask

首先舉個例子,獲取手機上視頻信息所需要的時間是個不能確定的事情。如果視頻很少,也許幾十毫秒就能完成,如果視頻很多(比如幾十個),也許就要花二十多秒。

安卓應用只有一個主線程-各個組件都是在這個線程中運行。作為組件的之一的Activity就是在這個線程中更新應用界面的,例如,用戶點擊界面上的一個按鈕,按鈕得到響應,整個過程就是在這個主線程裡。所以這個主線程絕對不可以做耗時的操作。假如在按鈕中做了耗時的操作,那麼當它進行耗時操作的時候,你去點擊界面上的其它按鈕是不會有反應的,就好像程序凍在了那裡。

代碼的執行一旦連續占用這個線程超過一定的時間,系統就會彈出“程序無響應的”提示。

因此,我們可以考慮把獲取視頻信息的操作放到一個單獨的線程thread中進行。

這就好比你在正在做一件事情A,突然另一件事情B來打擾你,你不得不停下手頭的工作來完成,做完了才能繼續之前的工作;這時如果有另外一個人(另一個線程)來幫助你,把事情B全部包攬了,那你就不用分心了。當另一個人把事情B做完後,告訴你一聲就可以了。

5.1 異步操作

啟動一個新的線程,分擔耗時工作的方法是一種異步操作:我讓你幫我做一件事情,布置任務後,我就去做其他的事情了,等你做完了再告訴我結果;

與它對應的是同步操作:我讓你幫我做一件事情,布置任務後,我啥也不做,就等著你做完了告訴我結果;

獲取視頻信息是個異步操作,啟動一個新線程-工作線程thread-查詢視頻信息,查詢完成後,工作線程再將結果通知到主線程,讓主線程將查詢到結果的結果顯示到界面上。界面的更新一定要在主線程中進行,不能在別的線程修改,否則系統後提示運行錯誤,這一點相當重要。因此我們一定要將查詢的結果發送給主線程,讓主線程處理界面的更新。

5.2 異步操作的方案

安卓系統提供的異步操作方案有:

創建工作線程thread和Handler,利用Handler在工作線程和主線程之間傳遞數據; 使用AsyncTask幫助類,AsyncTask中封裝了工作線程,通過AsyncTask完成工作線程和主線程之間的數據傳遞;

第1種方案,已經在第3節裡面介紹過了。

這裡我們介紹第2種方案。

AsyncTask實際上它也是通過方案1實現的,只不過Android SDK對這套機制做了進一步封裝,讓使用者用起來更加方便。

AsyncTask適用於,

使用場景簡單,只是單個任務的異步操作,沒有多個線程之間的數據同步考慮; 使用方便,不用考慮太多的新線程創建的細節;

5.3 AsyncTask的使用

AsyncTask需要被繼承成為一個新的子類來使用,在被繼承時,要指定三種參數的類型-Param Progress Result,還需要實現doInBackground(Param...)函數,此外通常還要實現onProgressUpdate(Progress...) onPostExecute(Result) 兩個回調函數。

class MyTask  extends AsyncTask {

    @Override
    protected Result doInBackground(Param... params) {
        return result;
    }

    @Override
    protected void onProgressUpdate(Progress... progresses) {

    }

    @Override
    protected void onPostExecute(Result result) {

    }

    @Override
    protected void onCancelled() {

    }
}

doInBackground(Param... params)函數:傳入參數的Param類型就是AsyncTask中指定的Param類型。它運行在新創建的工作線程當中。

使用MyTask時,要在主線程中使用excute()方法傳入不定長參數,讓Task運行起來,

MyTask task = new MyTask();
task.excute(param0, param1, ..., paramN);

不定長參數會以數組的形式傳遞到doInBackground()函數當中,

@Override
protected Result doInBackground(Param... params) {
    Param param0 = params[0];
    Param param1 = params[1];
    ......
    Param paramN = params[N];

    return result;
}

onProgressUpdate(Progress... progresses)函數:傳入參數的Progress類型就是AsyncTask中指定的Progress類型。

doInBackground()中執行的是一個很耗時的工作,有時需要向主線程報告當前的運行狀況,這就要使用到publishProgress()函數,publishProgress()也是使用的不定長參數,

@Override
protected Result doInBackground(Param... params) {
    ......
    publishProgress(progress1, progress2, ..., progressN)

    return result;
}

不定長參數會以數組的形式傳遞到onProgressUpdate()函數當中,

@Override
protected void onProgressUpdate(Progress... progresses) {
    Progress progress0 = progresses[0];
    Progress progress1 = progresses[1];
    ......
    Progress progressN = progresses[N];

}

onPostExecute(Result result)函數:傳入參數的Result類型就是AsyncTask中指定的Result類型。

doInBackground()函數返回的類型也是Result

@Override
protected Result doInBackground(Param... params) {
    ......

    return result;
}

返回的結果作為參數傳遞給onPostExecute()函數,

@Override
protected void onPostExecute(Result result) {

}

onCancel()函數會在調用者取消AsyncTask的工作的時候被觸發。

要取消AsyncTask的工作,首先要在主線程中調用cancel()方法,

task.cancel(true);

因為在doInBackground()中執行的是一個很耗時的工作,需要時不時的檢查自己是否被取消執行了,

@Override
protected Result doInBackground(Param... params) {
    ......
    if(isCancelled())
    {
        ......
        return result;
    }

    ......
    return result;
}

最後,onCancelled()函數會被觸發,這個函數會在主線程中被執行,

@Override
protected void onCancelled() {

}

綜合上面的分析,自定義一個AsyncTask的方法如下,

class MyTask extends AsyncTask {

    @Override
    protected Result doInBackground(Param... params) {
        Param param0 = params[0];
        Param param1 = params[1];
        ......
        Param paramN = params[N];

        while(!isCancelled())
        {
            ......
            publishProgress(progress1, progress2, ..., progressN);
        }

        return result;
    }

    @Override
    protected void onProgressUpdate(Progress... progresses) {
        Progress progress0 = progresses[0];
        Progress progress1 = progresses[1];
        ......
        Progress progressN = progresses[N];
        ......
    }

    @Override
    protected void onPostExecute(Result result) {

    }

    @Override
    protected void onCancelled() {

    }
}

使用一個AsyncTask的方法如下,

MyTask task = new MyTask();
task.excute(param0, param1, ..., paramN);
......    
task.cancel(true);
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved