Androidの非同期処理を試す
Androidアプリでスプラッシュ画面を表示させる方法 - MIRAI THE FUTURE
Androidでスプラッシュ画面を表示する方法を調べていたらHandlerを使った処理が出てきたので、ついでに非同期処理を調べてみました。
別スレッドから画面描画はできない
別スレッドからGUIの状態を変化させるメソッドtext.setText()などを呼び出すと、CalledFromWrongThreadExceptionが発生してアプリは落ちてしまいます。
11-28 14:52:25.179: ERROR/AndroidRuntime(412): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Handlerクラスを使うと、別のスレッドからVIEWに触れるスレッドへ処理を依頼することが出来ます。
そこで別スレッド内でHandlerを生成して、Runnableをpost()してみます。
11-28 15:10:59.899: ERROR/AndroidRuntime(464): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Looper.prepareから呼ばれてないスレッド内部からは、Handlerが生成できないそうです。
Handlerを描画スレッドからfinalで生成するようにしたら、GUIを更新できるようになりました。
AsyncTaskで可読性を向上させる
Handlerを使った処理のコードは入れ子の入れ子になるので、可読性が悪くなってしまいます。
下記のページでは、それを解決するAsyncTaskというクラスの利用方法について記載されていました。
throw Life - 初めてのAndroid -第7章 世界との接続-
AsyncTaskの実装クラスからexecute()を呼び出すと、doInBackgroundが開始されます。
その処理の結果はonPostExecute内で受け取ることができます。onPostExecute内の処理はHandler経由になるようで、VIEWを更新することができます。
execute()の引数と結果はジェネリクスで指定ができます。(ParamsとResult)
public class ThreadActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.thread); final TextView text = (TextView) findViewById(R.id.TextView01); Button button = (Button) findViewById(R.id.Button01); button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { new AsyncTask<Integer, Object, String>(){ @Override protected String doInBackground(Integer... params) { Integer integer = params[0]; return String.valueOf(integer); } @Override protected void onPostExecute(String result) { text.setText(result); } }.execute(1); } }); } }
参考ページ
throw Life - 初めてのAndroid -第7章 世界との接続-
Androidで学ぶ並列処理とGUI - やさしいデスマーチ
Androidで定期的に処理を実行する方法 | public static void main
書籍「ANDROID HACKS」非同期処理を行う p.153〜