2012年11月28日 星期三

[Android] 如何正確地停止正在執行中的AsyncTask?

 在上篇文章中,我們提到了如何正確安全地停止Java執行緒的方法,接下來不得不提的,就是在 Android API 中用以簡化執行緒工作的AsyncTask類別的停止方法

 在 Android 的開發中經常會使用到執行緒來進行長時間的工作,這些工作絕對不能放在 UI thread 裡(也就是負責畫面繪製與處理使用者互動的那個執行緒),否則一個按鈕按下去,UI thread 開始去進行那些所謂長時間的工作,後果就是整個畫面看起來「當掉了」,所以切記,在進行 Android 程式的開發時,絕對要依靠 working thread 或AsyncTask來進行那些工作。總之AsyncTask存在的意義與一般用法很多地方都有談了,在此就不再贅述。

 要停止一個已開始執行的AsyncTask,主要要透過它的cancel()方法,一個被呼叫過cancel()方法的AsyncTask它之後的isCancelled()必然會回傳true值。因此,我們就可以以類似 [Java] 如何安全且優雅地停止Java執行緒?一文的方法,將迴圈中的旗標值判斷替換為isCancel()回傳值的判斷,來決定doInBackground()中的工作是否要繼續執行。同樣的,這一樣會遇到工作不會立即停止的狀況,此時我們可以在呼叫cancel()方法時將其參數設為true,這即代表不但之後isCancel()的回傳值要變成true,而且立即對此AsyncTask發出InterruptedException,好馬上改變doInBackground()的程式流程,來完成停止執行的目的。

 與前述該文中程式碼效果相同的程式碼,請見下述所示:

public class TestTask extends AsyncTask<Void, Void, Void> 
{
    @Override
    public void doInBackground(Void... values)

    {
        Log.i(TAG, "TestTask starts");
        while(!
isCancelled()

        {
            try

            {
                //do something

                Log.i(TAG, "Sleeping...");
                Thread.sleep(5000);
            }

            catch(InterruptedException e) 
            {
                
Log.i(TAG, "TestTask was inturrupted");

            }
            catch(Exception e) {
                //handle error
                Log.e(TAG, e.toString(), e);
            }   
        }
        
Log.i(TAG, "TestTask ends");
    }
}
public class SomeActivity extends Activity 
{
    ....    public void someMethod()
    {
        TestTask task = new TestTask();
        task.execute();
        // wait for a minute
        task.cancel(true);
    }
}

沒有留言:

張貼留言