Android_スレッド処理

「Android_スレッド処理」の編集履歴(バックアップ)一覧はこちら

Android_スレッド処理」(2013/07/26 (金) 17:21:42) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

[[トップページ]] > [[Android]] > スレッド処理 ** スレッド処理の基本 ネットワークへのアクセスなどは、メインスレッドでは出来ないので、 別スレッドで行う。 こういう処理のときに、AsyncTaskを利用する。 また、AsyncTaskの経過処理を表示するのには、ProgressDialogが利用できる。 public void goTask() { AsyncTask<Void,Integer,Void> task = new AsyncTask<Void,Integer,Void>() { int total; int count; ProgressDialog dialog; protected void createDialog() { dialog = new ProgressDialog( this.MainActivity ); dialog.setTitle( "Working..." ); dialog.setMessage( "Wait for dummy"); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.setMax( 100 ); dialog.setProgress(0); dialog.show(); } @Override protected void onPreExecute() { super.onPreExecute(); createDialog(); } @Override protected void onPostExecute(Void params) { super.onPostExecute(params); dialog.dismiss(); } @Override protected Void doInBackground(Void... params) { count = 0; total = 100; for (int i=0;i<100;i++) { count += 1; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } publishProgress( count * 100 / total ); } return null; } @Override protected void onProgressUpdate(Integer... values) { dialog.setProgress(values[0]); super.onProgressUpdate(values); } }; task.execute( ); } (このgoTaskメソッドは、何かボタンを押したら呼ばれるようにしておく) ** デバイスの回転での問題点 これで動作するのだが、AsyncTaskが動作している間にデバイスを回転させてしまうと、プログレスバーが消えてしまう。 さらに、onPostExecuteのところのdialog.dismiss();のところでハングしてしまう。 この理由は、デバイスの回転にともなってアクティビティが削除/再生成されてしまうため。 アクティビティが再生成された場合でも、動作しているAsyncTaskが設定しているProgressDialogが削除された古い アクティビティを保持して動作しているため、dismiss出来なずにエラーが発生してしまうからだ。 これに対応するには、Android 3.0以後で導入されたDialogFragmentを使う方がよいようだ。 しかし、DialogFragmentはAndroid 2.3系では利用できないため、ここではProgressDialogのままで対応する方法を考える。 まず、Activityが破棄されたかどうかを知る必要がある。 このため、Activityに静的メンバとして、onCreateされた(最新の)Activityを保持することにする。 さらに、破棄された場合、新しいActivityから再度ProgressDialogを表示する必要があるが、サブスレッドからはGUIを 操作できないので、ハンドラを一つ用意しておく。 MainActivityに追加するフィールド public static MainActivity currentActivity; public Handler handler; そして、onCreateメソッド内で、次のように定義しておく currentActivity = this; handler = new Handler(); また、goTaskで定義しているAsyncTasxk内でもMainActivityを保持しておく。 ループ処理中、もしもactivityがcurrentActivityと違っていたら、handler経由で再度、 ProgressDialogを表示する。 public void goTask() { AsyncTask<Void,Integer,Void> task = new AsyncTask<Void,Integer,Void>() { MainActivity activity; int total; int count; ProgressDialog dialog; protected void createDialog() { dialog = new ProgressDialog( currentActivity ); dialog.setTitle( "Working..." ); dialog.setMessage( "Wait for dummy"); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.setMax( 100 ); dialog.setProgress(0); dialog.show(); } @Override protected void onPreExecute() { super.onPreExecute(); activity = currentActivity; createDialog(); } @Override protected void onPostExecute(Void params) { super.onPostExecute(params); if (activity == currentActivity) { dialog.dismiss(); } } @Override protected Void doInBackground(Void... params) { count = 0; total = 100; for (int i=0;i<100;i++) { count += 1; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if (activity != currentActivity) { activity = currentActivity; activity.handler.post(new Runnable() { @Override public void run() { createDialog(); } }); } publishProgress( count * 100 / total ); } return null; } @Override protected void onProgressUpdate(Integer... values) { dialog.setProgress(values[0]); super.onProgressUpdate(values); } }; task.execute( ); } これで一応、画面を回転させても再度プログレスバーを表示して動作継続するようにできた。 ちょっと面倒なので、もう少し良い方法があればいいのだけど。 2013/7/27
[[トップページ]] > [[Android]] > スレッド処理 ** スレッド処理の基本 ネットワークへのアクセスなどは、メインスレッドでは出来ないので、 別スレッドで行う。 こういう処理のときに、AsyncTaskを利用する。 また、AsyncTaskの経過処理を表示するのには、ProgressDialogが利用できる。 public void goTask() { AsyncTask<Void,Integer,Void> task = new AsyncTask<Void,Integer,Void>() { int total; int count; ProgressDialog dialog; protected void createDialog() { dialog = new ProgressDialog( this.MainActivity ); dialog.setTitle( "Working..." ); dialog.setMessage( "Wait for dummy"); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.setMax( 100 ); dialog.setProgress(0); dialog.show(); } @Override protected void onPreExecute() { super.onPreExecute(); createDialog(); } @Override protected void onPostExecute(Void params) { super.onPostExecute(params); dialog.dismiss(); } @Override protected Void doInBackground(Void... params) { count = 0; total = 100; for (int i=0;i<100;i++) { count += 1; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } publishProgress( count * 100 / total ); } return null; } @Override protected void onProgressUpdate(Integer... values) { dialog.setProgress(values[0]); super.onProgressUpdate(values); } }; task.execute( ); } (このgoTaskメソッドは、何かボタンを押したら呼ばれるようにしておく) ** デバイスの回転での問題点 これで動作するのだが、AsyncTaskが動作している間にデバイスを回転させてしまうと、プログレスバーが消えてしまう。 さらに、onPostExecuteのところのdialog.dismiss();のところでハングしてしまう。 この理由は、デバイスの回転にともなってアクティビティが削除/再生成されてしまうため。 アクティビティが再生成された場合でも、動作しているAsyncTaskが設定しているProgressDialogが削除された古い アクティビティを保持して動作しているため、dismiss出来なずにエラーが発生してしまうからだ。 これに対応するには、Android 3.0以後で導入されたDialogFragmentを使う方がよいようだ。 http://blog.zaq.ne.jp/oboe2uran/article/877/ しかし、DialogFragmentはAndroid 2.3系では利用できないため、ここではProgressDialogのままで対応する方法を考える。 まず、Activityが破棄されたかどうかを知る必要がある。 このため、Activityに静的メンバとして、onCreateされた(最新の)Activityを保持することにする。 さらに、破棄された場合、新しいActivityから再度ProgressDialogを表示する必要があるが、サブスレッドからはGUIを 操作できないので、ハンドラを一つ用意しておく。 MainActivityに追加するフィールド public static MainActivity currentActivity; public Handler handler; そして、onCreateメソッド内で、次のように定義しておく currentActivity = this; handler = new Handler(); また、goTaskで定義しているAsyncTasxk内でもMainActivityを保持しておく。 ループ処理中、もしもactivityがcurrentActivityと違っていたら、handler経由で再度、 ProgressDialogを表示する。 public void goTask() { AsyncTask<Void,Integer,Void> task = new AsyncTask<Void,Integer,Void>() { MainActivity activity; int total; int count; ProgressDialog dialog; protected void createDialog() { dialog = new ProgressDialog( currentActivity ); dialog.setTitle( "Working..." ); dialog.setMessage( "Wait for dummy"); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.setMax( 100 ); dialog.setProgress(0); dialog.show(); } @Override protected void onPreExecute() { super.onPreExecute(); activity = currentActivity; createDialog(); } @Override protected void onPostExecute(Void params) { super.onPostExecute(params); if (activity == currentActivity) { dialog.dismiss(); } } @Override protected Void doInBackground(Void... params) { count = 0; total = 100; for (int i=0;i<100;i++) { count += 1; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if (activity != currentActivity) { activity = currentActivity; activity.handler.post(new Runnable() { @Override public void run() { createDialog(); } }); } publishProgress( count * 100 / total ); } return null; } @Override protected void onProgressUpdate(Integer... values) { dialog.setProgress(values[0]); super.onProgressUpdate(values); } }; task.execute( ); } これで一応、画面を回転させても再度プログレスバーを表示して動作継続するようにできた。 ちょっと面倒なので、もう少し良い方法があればいいのだけど。 2013/7/27

表示オプション

横に並べて表示:
変化行の前後のみ表示: