読者です 読者をやめる 読者になる 読者になる

hyoromoのブログ

iOS/AndroidもしくはCocos2dxネタを書いています

UI部分を非同期処理させるよ

Android で UI 部分を非同期で処理させたい場合ってありますよね。
単にサービスやスレッドを利用しても可能でしょうが、もっと楽にできる方法があります。
その名も「AsyncTask」です。

AsyncTask

非同期処理を行う際の便利な API です。
冒頭でも述べましたが、これは UI の処理はさせたいけど別スレッドで処理させたい場合に便利です。
この処理の流れとしては、
コンストラクタ(ここで View などを渡しておく)」→「バックグラウンド処理」→「UI への描画処理」
となっています。

ソースレベルで解説

Activity にて非同期処理の書かれたクラスをインスタンス化して、executeメソッドを実行します。

クラス名 task = new クラス名(view); 
task.execute(何らかのデータ);
public class クラス名 extends AsyncTask<String, Integer, Drawable> {
    public DownloadTask(View v) {
        // View を受け取る処理
    }

    protected Drawable doInBackground(String... uri) {
         // バックグラウンド処理。
         // executeメソッドが呼ばれたら、このメソッドが初めに呼ばれる。
    }

    protected void onPostExecute(Drawable draw) {
        // UIヘの描画処理。mainスレッドで実行したことになる。
        // doInBackgroundメソッドの後で呼ばれる。
    }
}

ソース

私が書いた、画像を非同期通信で取得してくるソース。
単純にソースの一部を抽出しただけなので、おかしな点があるかもしれません。イメージを感じ取ってください。

// Activity
// 画像をダウンロードして表示する
private void downloadAndUpdateImage(View v, String imageStr) {
    DownloadTask task = new DownloadTask(v); 
     task.execute(imageStr);
}
public class DownloadTask extends AsyncTask<String, Integer, Drawable> {

    private View view;

    public DownloadTask(View v) {
        view = v;
    }
    
    public Drawable downloadImage(String uri) {
        URL url = null;
        try {
            url = new URL(uri);
            InputStream is = url.openStream();
            Drawable draw = Drawable.createFromStream(is, "");
            view.setTag(url.toExternalForm());
            is.close();
            return draw;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 独自スレッドでバックグラウンド処理
     * @param result
     */
    protected Drawable doInBackground(String... uri) {
        return downloadImage(uri[0]);
    }
    
    /**
     * 画面描画できるmainスレッドで実行したい処理
     */
    protected void onPostExecute(Drawable draw) {
        view.setBackgroundDrawable(draw);
    }
}

ソースはこちらに置いてます。全体を確認したい場合は参照してみてください。

まとめ

onCreateメソッド内で時間のかかる処理はできないため、一部表示させて後は非同期処理で行うのが良さそうですね。
色々と使いどころがありそうな API なので知っておいて損はないかと思います。

参考

throw Life -> 初めてのAndroid -第7章 世界との接続-
素晴らしいまとめです。私の記事なんか読むより大変参考になります。