Androidアプリのイベント処理とFragment
イベント処理の注意点
Androidのイベント処理を行う上で気をつけなければならないのは、Androidアプリは通常シングルスレッドで実行されているということです。
つまり、各イベントの処理は並行に行われることはないですし、あるイベントの処理に時間がかかっていればいくらボタンを押してもボタンのクリックイベントの処理は行われません。
HelloTabletActivity.java を修正して実験してみましょう。HelloTabletActivity.java の onCreate() メソッド内にあるクリックイベントを設定している箇所を以下のように修正します。
// button1をクリックした時に処理を実行できるようにする findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { try { // 10秒間Wait Thread.sleep(10 * 1000); } catch (InterruptedException ignore) { } new AlertDialog.Builder(HelloTabletActivity.this). setPositiveButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.cancel(); } }).setMessage("ボタンを押しました").show(); } });
実行してみると、ボタンを押してから約10秒後にダイアログが表示されるようになっていると思います。
ダイアログを閉じでボタンを何回か連続で押したり、戻るキーを押してみてください。先ほどとは違い、以下の画面が表示されます。
図2:ANRエラーダイアログ(クリックで拡大) |
おそらく、みなさんがAndroidアプリを使っていると、しばしば「ANRエラーダイアログ」(ANR: Application Not Responding)が表示されるかと思います。
「ANRエラーダイアログ」は以下のような場合に表示されます。
入力イベントに対して、5秒間以上アプリが反応しなかった場合
今回はボタンのクリックイベントの処理に10秒以上かかるようになっているので、以降のボタンのクリックイベントや、戻るキーイベントなどの入力イベントが5秒間以上処理されません。そのため、上記の条件に合致する形となり、「ANRエラーダイアログ」が表示されてしまいます。
このことから、Androidのイベント処理を実装する上で大切なことは「なるべく早く、イベント処理は終わらせる。」ということです。
もし、イベント処理に時間がかかってしまい「ANRエラーダイアログ」が表示されてしまうと、Android Marketのレビューコメントに辛辣なコメントが書かれてしまうことでしょう。
それを避けるためにも、入力イベントに応じて以下のような処理を行う場合はAsyncTaskなどのクラスを使って非同期処理を行うことを心掛けた設計・実装をしてください。
- ファイルの作成・削除・読み書き処理
- SDカードにアクセスする処理
- DB(SQLite)を用いる処理
- 通信処理
- 時間がかかることがわかっている計算処理
忘れがちなのが、アプリのバージョンアップに伴ってDBスキーマの変更を行う場合です。スキーマ変更の処理も非同期で行うようにしないと「ANRエラーダイアログ」が表示され、スキーマ変更が中途半端に強制終了される可能性もありますので注意が必要です。
上記の点に気をつけるだけでも「ANRエラーダイアログ」が表示される可能性は大きく減ります。設計段階からこのような点を意識しておくことを忘れないでください。
また、以下のURLにも「ANRエラーダイアログ」を回避するための方法が書いてあるので確認してください。
→参照:Designing for Responsiveness | Android Developers
Fragmentについて
Android3.0からFragmentという新たな機能が追加されました。Fragmentはある機能のUIや振舞いをActivityから切り離して管理し、再利用することを目的として導入された機能です。
今回はFragmentが導入された背景とサンプルアプリで実際の動作を確認してみます。
Fragmentが必要となった背景
Androidは1つの画面に1つのActivityという設計方針で設計・実装されています。画面が比較的小さく、画面の縦幅のほうが長いスマートフォンだけが対象のころはこれでもまだ良かったのですが、画面が大きく、横幅のほうが長いタブレット端末でもAndroidが動作するようになってからはいろいろと弊害もでてきました。
例えば、設定画面を作る際、スマートフォンであれば設定一覧画面から設定詳細画面に画面遷移するような作りが望ましいですし、タブレット端末であれば設定画面の左側に設定一覧、右側に設定詳細が表示され、設定一覧の選択で右側の設定詳細の表示内容が切り替わるような作りが望ましいです。この時、設定画面としての画面レイアウトはスマートフォンとタブレット端末で異なりますが、設定一覧や設定詳細のUIや振舞いは共通で使いまわせればベストです。
しかし、Android2.xまでの機能では1画面に1つのActivityという制約があるため、スマートフォンで作っていた設定一覧画面や設定詳細画面を1つの設定画面にまとめるためには、各画面のUIや振舞いを1つのActivityにコピーして作成する必要がありました。これではUIや振舞いに変更があった場合の修正が大変になります。
そこで、Android3.0からはUIや振舞いをActivityから切り離して管理できるFragment 機能が追加されました。これにより、スマートフォンとタブレット端末間で、機能のUIや振舞いを共通して使いまわせるようになりました。
なお、Fragment機能はAndroid4.0でもサポートされていますので、タブレット端末向けにFragment機能を用いて作成したアプリは比較的容易にAndroid4.0対応のスマートフォンに対応できると思います。
次ページでは、実際にFragmentを使ったサンプルアプリを作ってみます。