[Android] AsyncTask:非同期処理を実装する

AsyncTaskは、バックグラウンドで非同期処理を実行し、結果を画面に反映するという処理の流れを容易に実装することができます。ここではAsyncTaskの概要と実装方法について説明します。
広 告
目次
前提条件
- 特になし
動作確認端末
- Google Nexus 7 – 5.1.1 – API22(実機)
1. AsyncTaskとは
AsyncTask
は、ThreadとHandlerを使った処理のヘルパークラスで、バックグラウンドで非同期処理を実行し(②)、その処理結果を画面に反映する(⑤)、という処理の流れを容易に実装することができます。
このクラスを利用した処理は、実行時間が数秒程度のバックグランド処理を想定されているため、より長い時間のかかる処理を実装したい場合は、java.util.concurrent
に含まれる、Executor、ThreadPoolExecutor、FutureTask、などを利用することが推奨されています。
2. AsyncTaskの実装例
ここではAsyncTaskの実装例を見ていきます。
AsyncTask
はAsyncTaskクラスを継承したクラス(サブラクス)として作成する必要があります。そして、少なくともdoInBackground(Params…)メソッドをオーバーライドして実装しなければなりません。
以下に、ファイルのダウンロード処理を想定したAsyncTask
のサンプルコードを示します。
AsyncTaskの実装例
import android.os.AsyncTask; import java.net.URL; /** ファイルのダウンロード処理を非同期実行する */ public final class DownloadTask extends AsyncTask<URL, Integer, Long> { @Override protected void onPreExecute() { super.onPreExecute(); // 一番最初に実行される // UIスレッド上でプログレスバーを表示する showProgress(); } @Override protected Long doInBackground(URL... urls) { // onPreExecute()メソッド実行後に呼び出される // AsyncTask #◯」という名前のWORKERスレッドで // ファイルのダウンロード処理を実行する // 受け取ったURLの数 final int count = urls.length; // ファイルのダウンロード合計サイズ long totalSize = 0; for (int i = 0; i < count; i++) { // ファイルのダウンロード合計サイズを加算 totalSize += downloadFile(urls[i]); // 現在の進捗率を設定 publishProgress((int) ((i / (float) count) * 100)); if (isCancelled()) { // cancel()メソッドが呼び出された場合は // 残処理を中断する break; } } return totalSize; } @Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress); // publishProgress()が実行されると呼び出される // UIスレッドで進捗バーを更新する setProgressPercent(progress[0]); } @Override protected void onPostExecute(Long result) { super.onPostExecute(result); // doInBackground()からreturnされると呼び出される // UIスレッドで処理結果をトースト表示する showToast("Downloaded " + result + " bytes"); } }
上記コードでは、AsyncTask
のメソッド以外(download()
、setProgressPercent()
、showToast()
)の処理については省いています。ソースコードの概要についてはソース上のコメントを参照してください。
そしてこのDownloadTask
を実行するためには、Activity
から以下のようなコードを実行します。
DownloadTaskを呼び出すコード
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); .... final DownloadTask task = new DownloadTask(); // DownloadTaskを実行する // 引数がdoInBackground()メソッドに渡される task.execute(url1, url2, url3); }
気をつけるべき点としては、execute(Params…)メソッドはUIスレッドから実行しなければならないというルールがあるため、Activity
などのライフサイクルメソッド上などで実行するようにしてください。
3. 3つの総称型
AsyncTaskを継承すると、AsyncTask<Params,Progress,Result>
のように3つの総称型を定義する必要があります。以下に、各々の型についての説明します。
- Params
- バックグランド処理に渡される値の型です。doInBackground(Params…)に渡される引数の型になります。
- Progress
- 進捗状況を更新する処理に渡される値の型です。publishProgress(Progress…)に渡す値の型、onProgressUpdate(Progress…)に渡される値の型になります。
- Result
- 結果を画面に反映する処理に渡される値の型です。doInBackground(Params…)の戻り値の型、onPostExecute(Result)に渡される引数の型になります。
AsyncTask
では、これらの値が全て必ず使用される訳ではありません。もし使用しない場合は、Void
を指定してください。
Void型を指定する場合
public final DownloadTask extends AsyncTask<Void,Void,Void>
4. AsyncTaskの実装に必要な4つのメソッド
AsyncTaskを実装する上で主に使用されるメソッドが4つあります。以下にそれぞれのメソッドの説明を記します。
- onPreExecute():事前処理を実行する
- onPreExecute()メソッドはUIスレッドで実行されます。
AsyncTask
が実行されると1番始めに実行されます。このメソッドでは、進捗状況を画面に表示するためのプログレスバーを生成し表示する処理など定義されます。 - doInBackground():非同期処理を実行する
- 「
AsyncTask #1
」などのような名称のWORKERスレッドで実行されます。onPreExecute()メソッドの処理完了直後に実行されます。このメソッドでは、ネットワーク処理など時間のかかる処理を実行します。必要に応じてpublishProgress(Progress…)を実行し、onProgressUpdate(Progress…)に現在の進捗状況を渡します。 - onProgressUpdate():進捗状況を反映する
- UIスレッドで実行されます。publishProgress(Progress…)が実行されると呼び出されます。引数には、publishProgress(Progress…)に設定された値が渡されます。このメソッドでは、予め生成してあったプログレスバーに対し現在の処理の進捗率を設定するなどを行います。
- onPostExecute():処理結果を画面に反映する
- UIスレッドで実行されます。doInBackground(Params…)の処理完了直後に呼び出されます。
5. 参考URL
AsyncTask | Android Developer
http://developer.android.com/intl/ja/reference/android/os/AsyncTask.html