このTipsはJava言語をある程度学んでいる方を前提にしています。
Web通信するAndroidアプリを開発する上で、AsyncTaskという非同期クラスを使う事になりました。その時に学んだ事を備忘録として記録します。
AsyncTaskに翻弄されている方の助けになればと思います。
サンプルコード
Android Developersに載っているサンプルコードです。AsyncTaskを継承して実装しています。
AsyncTaskは、呼び出し側と非同期で実行したい場合に使います。なので、呼び出し側はクラスをインスタンス化して実行(executeメソッド)する事になります。(呼び出し方は後述)
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
ジェネリクス
AsyncTaskを継承してクラスを作成していますが、AsyncTaskはジェネリクスを使用しているため継承する時に以下のような記述になります。
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
}
ジェネリクス(総称型)というのは、クラスが引数の型を定めない場合に使うんだそうです。ここではとりあえずそう覚えておきます。
このサンプルでは、 URL, Integer, Long となっていますが、型が決まっていないので、クラスの実装によって他の型になります。
doInbackgroundメソッドと可変長引数
AsyncTaskには必ずオーバーライドしなければならないabstructメソッドとして、doInBackgroundがあります。
doInBackgroundは、AsyncTaskが(非同期に)実行された時に裏側で動くいちばんメインの処理を記述します。
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
引数はピリオドが3つついたもの (URL... urls) となっています。
これは可変長引数と言って、受け取るのはurls[]配列変数となります。
なぜ配列変数の引数にしないかというと、呼び出す側には羅列して書いていいので、呼び出す前にいちいち配列を作らなくていいというメリットがあるからだそうです。(呼び出し方は後述)
doInBackgroundメソッドの引数 (URL... urls) は、クラス継承する時にジェネリクスで指定した1つ目の型です。戻り値の totalSize は、3つ目の型(ここではLONG型として戻す)です。
呼び出し側
呼び出し側の記述です。
new DownloadFilesTask().execute(url1, url2, url3);
executeメソッドで実行するとdoInBackgroundメソッドの処理が裏側で動きます。
url1とurl2とurl3が、可変長引数として(結局は配列変数として)渡されます。
onPostExecuteメソッド
サンプルで、AsyncTaskのonPostExecuteというメソッドを記述しています。
このメソッドは、doInBackgroundの処理が終わった後に呼び出されます。
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
doPostExecuteメソッドの引数 result は、doInBackgroundの戻り値がセットされます。
ジェネリクス再び
最初に戻って、クラスを継承した時にジェネリクスに指定する1つ目の型はdoInBackgroundの引数と、3つ目の型はdoInBackgroundの戻り値(=onPostExecuteの引数)と合わせましょう。
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
}
ぶっちゃけAndroidアプリ開発は、アプリ開発にあたってとりあえず知っておくべきことをズバリ書きます。例外はありますのでご了承ください。
勉強中の身でありますので、誤りなどあればご指摘いただけると有り難いです。