AsyncTask異步加載

異步任務——AsyncTask
1. 用處:
將耗時操作放在非主線程中執行,既保證了Android單線程模型,也保證了程序的響應(不出現ANR)
AsyncTask在子線程中更新UI,封裝、簡化異步操作
2. AsyncTask <\Params, Progress, Result>
是一個抽象類,通常用於被繼承,繼承AsyncTask需要指定如下三個泛型參數:
Params:啓動任務時輸入參數的類型
Progress:後臺任務執行中返回進度值的類型
Result:後臺執行任務完成後返回結果的類型
注意:參數不是一定要使用, private class MyTask extends AsyncTask<\Void, Void, Void> { … }
3. 構建AsyncTask子類的回調方法:
onPreExecute:執行後太耗時操作前被調用,通常用戶完成一些初始化操作
doInBackground:必須重寫,異步執行後臺線程將要完成的任務
onProgressUpdate:在doInBackground()方法中調用publishProgress()方法更新任務的執行進度後,就會觸發該方法
onPostExecute:當doInBackground()完成後,系統自動調用該方法
只有doInBackground方法運行在子線程,其他幾個方法都運行在ui線程

ImageTest.java
該實例實現了網絡加載圖片。

public class ImageTest extends Activity {

    private ImageView mImageView;
    private ProgressBar mProgressBar;
    private static String URL = "";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image);
        mImageView = (ImageView) findViewById(R.id.image);
        mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
        new MyAsyncTask().execute(URL);

    }

    class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mProgressBar.setVisibility(View.VISIBLE);
        }

        @Override
        protected Bitmap doInBackground(String... params) { //傳遞進來一個可變長的數組
            String url = params[0];
            Bitmap bitmap = null;
            URLConnection connection;
            InputStream is;
            try {
                connection = new URL(url).openConnection();
                is = connection.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                Thread.sleep(3000); //令線程睡眠3s以便觀察
                bitmap = BitmapFactory.decodeStream(bis);
                is.close();
                bis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            mProgressBar.setVisibility(View.GONE);
            mImageView.setImageBitmap(bitmap);
        }

    }
}

ProgressBarTest.java
該實例模擬了進度條的顯示。
AsyncTask底層是通過線程池實現的,一個線程必須結束後,另一個task纔會開始執行。因此,當希望結束當前task時,需要在Activity的onPause方法中添加cancel方法。然而默認情況下取消AsyncTask(設置mTask.cancel(true);)無法真正結束線程,必須在doInBackground和onProgressUpdate方法中結束循環或中斷方法。

public class ProgressBarTest extends Activity {

    private ProgressBar mProgressBar;
    private MyAsyncTask mTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progressbar);
        mProgressBar = (ProgressBar) findViewById(R.id.pg);
        mTask = new MyAsyncTask();
        mTask.execute();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mTask != null && mTask.getStatus() == Status.RUNNING) {
            //cancel方法只是將對應的AsyncTask標記爲cancel狀態,並不是真正地取消線程的執行
            mTask.cancel(true);
        }
    }

    class MyAsyncTask extends AsyncTask<Void, Integer, Void> {

        @Override
        protected Void doInBackground(Void... params) {
            //模擬進度更新
            for (int i = 0; i < 100; i++) {
                if (isCancelled()) {
                    break;
                }
                publishProgress(i); //將參數傳遞給onProgressUpdate
                try {
                    Thread.sleep(300); //令線程睡眠300ms
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            if (isCancelled()) {
                return;
            }
            //獲取進度更新值
            mProgressBar.setProgress(values[0]);
        }

    }

}

AsyncTask注意事項
1. 必須在UI線程中創建AsyncTask的實例。即在MainActivity中初始化MyAsyncTask task = new MyAsyncTask();
2. 必須在UI線程中調用AsyncTask的execute()方法,即在MainActivity中調用task.execute()方法。
3. 重寫的四個方法是系統自動調用的,不應手動調用
4. 每個AsyncTask只能被執行一次,多次調用將會引發異常

發佈了37 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章