Android でダイアログを表示する例として、以下のようなコードが紹介されている。多くの場合は、Activity の onStart() メソッドから呼び出すようになっている。
private void show() { AlertDialog.Builder dialog = new AlertDialog.Builder(context); dialog.setTitle(context.getString("タイトル"); dialog.setItems( new String[] { context.getString("ボタン1"), context.getString("ボタン2") }, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { switch (which) { case 0: // do something break; case 1: // do something break; default: // error break; } } }); dialog.show(); }
ダイアログなんて何も考えなくても・・・と思ったのが間違いだった。ここから、長いことダイアログと苦闘することになる。きっかけは、Android 開発ガイドの翻訳になんか注意事項が書いてあったなぁというおぼろげな記憶が戻ってきたことだった。開発ガイドの翻訳を見直してみると、以下のような記述があった。
ダイアログは常に Activity の部品として作成され表示されます。通常はアクティビティ内の onCreateDialog(int) コールバックメソッドからダイアログを生成します。
さらに注意事項が。
注意: onCreateDialog() メソッドの外部でダイアログを作成してしまうと、アクティビティにアタッチされません。しかしながら、 setOwnerActivity(Activity) でアクティビティにアタッチすることができます。
恥ずかしいことに、最初に記述したメソッドは View に定義していた。ダイアログを表示したまま、Android の画面を転回すると、「Activity … has leaked window com.internal.policy.imple…」というエラーが logcat に出力された。画面を転回したことで、Activity が一度終了してロードし直されている。そのタイミングで、ダイアログが Activity のライフサイクルと同期していないのでメモリーリークしているということなのだろう。
正しくは、onCreateDialog(int id) メソッドの中でダイアログを生成、showDialog(id)メソッドでダイアログを呼び出せばよい。サンプルコードを見てみると、Dialog の create() メソッドは呼び出しているが、show() メソッドは呼び出していない。create() メソッドを呼び出して戻してあげると Android がダイアログを表示してくれるということらしい。onCreateDialog メソッドの中で、id で分岐する必要があるため、switch 文を書かないといけなくてあまり美しくない(if else でもいいけど)。
でも、メモリーリークはまずいので実際にやってみると・・・showDialog メソッドが deprecated と言われてしまった。どうも、新しいドキュメントを参照しなければならないらしい。本家のドキュメントでDialogsを読むと、いきなり「Creating a Dialog Fragment」の文字が。Fragment って Android 3.0からのサポートじゃなかったかしら・・・(続く)。