AsyncTaskは、何かしらの重い処理(大きなファイルの読み込みやインターネットからのデータの取得等々)を行うとき、
UIスレッドを止めないようにするために使うクラスである。
もしUIスレッド上でこれらの重い処理を行うと、UIの表示が固まったように見えてしまい、操作性が良くない。
そこで、AsyncTaskを用い、重い処理は別のスレッドで行うようにし、UI側ではプログレスバー等を表示しておいて
別スレッドでの処理が終わったらプログレスバーの表示を消して元の操作に戻れるようにするようなプログラムを書いてみる。
以下がそのプログラムである。
package com.lesson.progress; // インポートは省略 public class Main extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // ボタン押下時の処理 // タスクを開始する new MyTask().execute(new Object[]{}); } }); } /** * タスクサンプル * ジェネリクスの型の意味は、 * ・タスク開始時:doInBackground()に渡す引数の型 * ・進捗率を表示させるとき:onProgressUpdate()に使う型 * ・タスク終了時:doInBackground()の返り値の型 */ public class MyTask extends AsyncTask<Object, Integer, Boolean> { // 処理中ダイアログ private ProgressDialog progressDialog = null; // タスク開始前処理:UIスレッドで実行される @Override protected void onPreExecute() { // 進捗ダイアログ表示 progressDialog = new ProgressDialog(Main.this); progressDialog.setMessage("now progressing..."); progressDialog.setIndeterminate(false); progressDialog.setCancelable(false); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setProgress(0); progressDialog.setMax(100); progressDialog.show(); Log.d("Main", "onPreExecute"); } // プログレスバー更新処理: UIスレッドで実行される @Override protected void onProgressUpdate(Integer... values) { progressDialog.setProgress(values[0]); Log.d("Main", "onProgressUpdate " + values[0]); } // バックスレッドで実行する処理 @Override protected Boolean doInBackground(Object... params) { // 重い処理(10秒待つ) try { for( int i=0; i<100; i++ ){ // 進捗ダイアログに表示する値を更新する // publishProgressを呼ぶと、UIスレッドでonProgressUpdateが実行される publishProgress(i+1); Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } Log.d("Main", "doInBackground"); return true; } // タスク終了後処理:UIスレッドで実行される @Override protected void onPostExecute(Boolean result) { // 進捗ダイアログをクローズ progressDialog.dismiss(); Log.d("Main", "onPostExecute"); } } }
基本的にはAsyncTaskを継承して、
doInBackground()等のメソッドを必要に応じてオーバーライドしていくことになるのだが、
これらのメソッドがどのスレッド上で行われるのかを把握しておく必要がある。
間違えると、Androidプログラミングでは禁止されている
「UIスレッド以外のスレッドがUIを操作する」プログラムを書いてしまう
ことになるので注意が必要となる。
用意したのはこんな画面。
ボタンを押すと・・・
このように、プログレスバーが表示される。