AsyncTaskを使った非同期処理|Android開発

      2018/06/15

通常、UIに変更を加える場合はUIスレッド上で実行する必要があります。しかしAsyncTaskを使用するとその部分を意識しなくて良くなります。
UI操作をUIスレッドで行わずに例外発生というのはよくある事(私だけ?)なので、非常に便利です。
また、UIスレッドへ投げる処理の記述が無くなるため、ソースコードがスッキリします。
※但しdoInBackgroundでUI操作は行えません。ここはあくまで別スレッド扱いみたいですね。

基本的な使い方

下記の様にAsyncTaskを継承したクラスを実装します。各メソッドの役割は以下。

  • onPreExecute
    バックグラウンド処理実行前の前処理を行います。(プログレスを表示など)
  • doInBackground
    バックグラウンド処理を行います。
  • onProgressUpdate
    バックグラウンド処理中の進捗更新を行います。(プログレスを更新など)
  • onPostExecute
    バックグラウンド処理終了時の処理を行います。(プログレスを消去など)
public class SampleAsyncTask extends AsyncTask<Void, Integer, Boolean> {

    @Override
    protected void onPreExecute() {
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        for (int i = 0; i <= 100; i++) {
            publishProgress(i);
        }

        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        // このサンプルでは progress[0] が進捗.
    }

    @Override
    protected void onPostExecute(Boolean result) {
    }
}

AsyncTaskに指定しているジェネリクスは順番に以下のもの。

  • doInBackground引数の型
  • onProgressUpdate引数の型
  • onPostExecute引数の型

  • doInBackgroundの戻り値は、onPostExecuteの引数になる。
  • onProgressUpdatedoInBackgroundから呼び出す。
  • doInBackground以外は実装必須ではない。(必要な場合のみ実装する)

使用例

下記は画像ファイルをバックグラウンドで読み込み、そのオブジェクトをコールバックで通知するものです。

AsyncTask継承クラス

public class BitmapLoadTask extends AsyncTask {
    public interface IBitmapLoadCallback {
        void onLoadCompleted(Bitmap bmp);
        void onLoadFailed();
    }

    private String mLoadFilepath;
    private IBitmapLoadCallback mCallback;

    public BitmapLoadTask(String filepath, IBitmapLoadCallback callback) {
        if (callback == null) {
            callback = new IBitmapLoadCallback() {
                @Override
                public void onLoadCompleted(Bitmap bmp) { }
                @Override
                public void onLoadFailed() { }
            };
        }
        mCallback = callback;
        mLoadFilepath = filepath;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Bitmap doInBackground(Void... params) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(mLoadFilepath, options);
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        if (result == null) {
            mCallback.onLoadFailed();
        } else {
            mCallback.onLoadCompleted(result);
        }
    }
}

使用例

new BitmapLoadTask("sample.jpg", new BitmapLoadTask.IBitmapLoadCallback() {

    @Override
    public void onLoadCompleted(Bitmap bmp) {
        // 受け取った Bitmap をUIに設定したりする.
        // この時、UIスレッドかどうかを意識する必要がない.
    }

    @Override
    public void onLoadFailed() {

    }
}).execute();

 - Android