今回は、AndroidのAsyncTaskについて。
知らない人のためにまずは、AsyncTaskの説明を。
Androidはメインスレッド內(nèi)でDB接続等の時(shí)間のかかる処理を行うとその間、
畫(huà)面はフリーズしてしまいます。
ボタンクリック時(shí)にDBへの登録処理を行い、
その間畫(huà)面にはプログレスバー(くるくるするやつ)を表示しておきたいとします。
この時(shí)、メインスレッド(GUIスレッド)でプログレスバーを表示、そのまま同じスレッドで
登録処理を行うと、畫(huà)面に表示されているプログレスバーは止まってしまいます。
これを解消するには、登録処理等のバックグラウンドで行いたい処理はメインスレッドとは
別のスレッドで行う必要があります。
この時(shí)、気をつけないと行けないのがバックグラウンドで動(dòng)かしているスレッドから
UI操作を行うとエラーが発生してしまいます。
上記のような動(dòng)作を簡(jiǎn)単に実裝できるのがAsyncTaskです。
以下に簡(jiǎn)単なサンプルを。
- public class SampleActivity extends Activity {
-
- /* ダイアログ(くるくるするやつ) */
- private ProgressDialog dialog;
-
- @Override
- public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.sample);
-
- final Button submitButton = (Button)findViewById(R.id.submitButton);
- submitButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- // くるくるを表示
- dialog = new ProgressDialog(SampleActivity.this);
- dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
- dialog.setMessage("登録中");
- dialog.show();
-
- // AsyncTaskを開(kāi)始
- final SampleTask task = new SampleTask();
- task.execute();
- }
- });
- }
-
- /**
- * バックグラウンド処理を行うクラス
- */
- class SampleTask extends AsyncTask<Void, Void, Void> {
-
- /**
- * executeが実行された後に実行される。
- */
- @Override
- protected void doInBackground(Void... params) {
- // DB登録等のUIに関與しない処理
- }
-
- /**
- * doInBackgroundの後に実行される。
- * このメソッド內(nèi)ではUIを操作できる。
- */
- @Override
- public void onPostExecute(Void... params) {
- // くるくるを消去
- dialog.dismess();
- }
- }
- }
こんな感じになります。
ただAsyncTaskを內(nèi)部クラスにするのがいやっていうか、だいたいここで行われる処理っていうのは
ビシネスロジックになることが多いので、Activityとは分離しておきたいので
別クラスにしたいところです。
ただ、そうするとAsyncTaskからUIを操作するために
AsyncTaskにActivityの參照を渡す必要が出てきてしまいます。
まあ、DB等にアクセスするためにはActivityが必要だったりするんですけど
畫(huà)面?zhèn)€別のUI処理が入ってくる場(chǎng)合はどうしても、
畫(huà)面固有のActivity(XxxxActivityみたいな)の型の參照を渡さなくてはいけなくて嫌な感じです。
できるだけ、Activityとして渡すに留めたい。そこで以下のような感じはどうでしょう?
まずは、以下のようなインターフェースを用意。
- public interface Callback {
-
- /** 成功時(shí)のレスポンスコード */
- public static final int SUCCESS = 0;
-
- /** 失敗時(shí)のレスポンスコード */
- public static final int ERROR = -1;
-
- /**
- * コールバックメソッド
- */
- public void callback(final int responseCode, final int requestCode,
- final Map<String, Object> resultMap);
-
- }
次にActivity。
- public class SampleActivity extends BaseNoMapActivity implements Callback {
- /* ダイアログ(くるくるするやつ) */
- private ProgressDialog dialog;
-
- private static final String REQUEST_CODE = "sample";
-
- @Override
- public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.sample);
-
- final Button submitButton = (Button)findViewById(R.id.submitButton);
- submitButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(final View v) {
- // くるくるを表示
- dialog = new ProgressDialog(SampleActivity.this);
- dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
- dialog.setMessage("登録中");
- dialog.show();
-
- // AsyncTaskを開(kāi)始
- final SampleTask task = new SampleTask(SampleActivity.this, REQUEST_CODE);
- task.execute();
- }
- });
- }
-
- /**
- * コールバックメソッド。
- * バックグラウンド処理終了後に呼び出される。
- */
- public void callback(final int responseCode, final int requestCode,
- final Map<String, Object> resultMap) {
-
- if (REQUEST_CODE.equals(requestCode)) {
- dialog.dismess();
- }
- }
- }
そして、AsyncTask。
- class SampleTask extends AsyncTask<Void, Void, Void> {
-
- /** コールバック */
- private Callback callback;
-
- /** リクエストコード */
- private String requestCode;
-
- /** コールバックの引數(shù)に渡す結(jié)果データ */
- private Map<String, Object> resultMap;
-
- /**
- * コンストラクタ.
- */
- public SampleTask(final Callback callback, final String requestCode) {
- this.callback = callback;
- this.requestCode = requestCode;
-
- resultMap = new HashMap<String, Object>();
- }
-
- /**
- * executeが実行された後に実行される。
- */
- @Override
- protected void doInBackground(Void... params) {
- // DB登録等のUIに関與しない処理
- // resuletMapにActivityに渡した値を詰めたり
- }
-
- /**
- * コールバックメソッドを?qū)g行する。
- */
- @Override
- public void onPostExecute(Void... params) {
- callback.callback(Callback.OK, requestCode, resultMap);
- }
- }
こんな感じです。
まずは、Callbackインターフェースですが、これでAsyncTackからActivityに処理を戻せるようにしています。
callbackメソッドによりActivityは「どのTaskを?qū)g行したのか」「成功したのか?」「結(jié)果データは?」と
といったものを受け取れるので、それに応じたUI処理を行えば良くなります。
考え方的にには、ActivityのstartActivityForResultとonActivityResultの考え方と同じです。
これなら、ある程度役割を分割できるのではないでしょうか。
|