AsyncTask總結

AsyncTask是android提供的輕量級的異步類,是針對子線程中更新UI,封裝簡化異步操作的封裝好的組件。Android的耗時操作如:網絡操作、讀取文件等如果放在主線程中會出現ANR(Application Not Responding)錯誤,使用AsyncTask可以保證Android的單線程模型,也避免了ANR。

構建AsyncTask子類的參數

AsyncTask<Params,Progress,Result>是一個抽象類,通常用於被繼承,繼承AsyncTask需要指定如下三個泛型參數:

  • Params: 啓動任務時輸入參數的類型
  • Progress: 後臺執行任務中返回進度值的類型
  • Result: 後臺執行任務完成後返回結果的類型

構建AsyncTask子類的回調方法

  • doInBackground: 必須重寫,異步執行後臺線程將要完成的任務
  • onPreExecute: 執行後臺耗時操作前被調用,通常用戶完成一些初始化操作
  • onPostExecute: 當doInBackgroud()完成後,系統會自動調用onPostExecute()方法,並將doInBackgroud()方法返回的值傳給該方法
  • onProgressUpdate: 在doInBackgroud()方法中調用publishProgress()方法
  • doInBackground運行在子線程,其他方法都運行在主線程

注意事項

  • 必須在UI線程中創建AsyncTask的實例
  • 必須在UI線程中調用AsyncTask的execute()方法
  • 重寫的四個方法是系統自動調用的,不應手動調用
  • 每個AsyncTask只能被執行一次,多次調用將會引發異常

案例一:回調方法的執行順序

package com.example.asynctask;

import android.os.AsyncTask;

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

    @Override
    protected Void doInBackground(Void... params) {
        System.out.println("=========doInBackground===========");
        return null;
    }

    @Override
    protected void onPreExecute() {
        System.out.println("=========onPreExecute===========");
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void result) {
        System.out.println("=========onPostExecute===========");
        super.onPostExecute(result);
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        System.out.println("=========onProgressUpdate===========");
        super.onProgressUpdate(values);//獲取進度值,更新進度條
    }

}

執行結果爲:
這裏寫圖片描述
在doInBackground中添加publishProgress()方法

@Override
    protected Void doInBackground(Void... params) {
        System.out.println("=========doInBackground===========");
        publishProgress();//傳入進度值
        return null;
    }

執行結果爲:
這裏寫圖片描述


案例二:加載一張網絡圖片

這裏寫圖片描述

佈局文件activity_image.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ProgressBar
        android:id="@+id/progressbar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:visibility="gone" />

</RelativeLayout>

ImageActivity

package com.example.asynctask;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

public class ImageActivity extends Activity {

    private ImageView mImageView;
    private ProgressBar mProgressBar;
    private static String URL = "https://img-my.csdn.net/uploads/avatar/6/A/7/1_leoleohan.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_image);
        mImageView = (ImageView) findViewById(R.id.image);
        mProgressBar = (ProgressBar) findViewById(R.id.progressbar);
        // 設置傳遞進去的參數
        new MyAsyncTask().execute(URL);

    }

    /**
     * Params:啓動任務時輸入參數的類型,這裏傳入url,是String類型 ;Progress:後臺任務執行中返回進度值的類型。這裏填Void
     * Result:後臺執行任務完成後返回結果的類型。這裏需要返回一個Bitmap
     * 
     * @author LeoLeoHan
     * 
     */
    class MyAsyncTask extends AsyncTask<String, Void, Bitmap> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mProgressBar.setVisibility(View.VISIBLE);// 顯示控件
        }

        /**
         * 獲取返回的結果,運行在主線程,所以可以對UI進行操作
         */
        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            mProgressBar.setVisibility(View.GONE);
            mImageView.setImageBitmap(bitmap);
        }

        /**
         * 運行在子線程中,開始真正的異步操作
         */
        @Override
        protected Bitmap doInBackground(String... params) {
            // String... params是可變長的數組,第0位就是傳進來的url
            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);
                bitmap = BitmapFactory.decodeStream(bis);// 將輸入流解析成bitmap
                is.close();
                bis.close();

            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            // 將bitmap作爲參數返回
            return bitmap;
        }

    }
}

案例三:模擬進度條

這裏寫圖片描述

佈局文件activity_image.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:padding="16dp"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >


    <ProgressBar
        android:id="@+id/pg"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

ProgressBarActivity

package com.example.asynctask;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ProgressBar;

public class ProgressBarActivity extends Activity {

    private ProgressBar mProgressBar;
    private MyAsyncTask myAsyncTask;

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

    @Override
    protected void onPause() {
        super.onPause();
        if (myAsyncTask != null
                && myAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
            // cancel方法只是將對應的asynctask標記爲cancel狀態,並不是真正的取消線程的執行
            myAsyncTask.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);
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return null;
        }

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

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