2011年04月02日

AndroidでDialog〜DialogFragmentの使い方〜

〜前置き〜

前にAndroidのDialogの使い方についての記事書いたけど、
いくつかコメントもらったりしたので、新しい情報で書いてみようかな。
ちなみに、Fragmentについては、互換パッケージを使った場合だよ。

まず、Androidの表示の仕方の基本パターンだけど3つかな。

1.Activity#onCreateDialog(int)をオーバーライドして、Activity#showDialog(int)を呼び出す。
2.Activity#onCreateDialog(int, Bundle)をオーバーライドして、Activity#showDialog(int, Bundle)を使用する。
3.DialogFragmentを継承して、FragmentActivityに表示する。

ちょっと凝ったことをしたいなら、迷わず3かな。
それぞれの特徴を、個人的な視点で書いてみるね。

1の場合:

Android1.6(API Level4)で使える。
前の記事の通り、動的なパラメーター表示関連に激しく弱い。

2の場合:

Android2.2(API Level8)から使える。
弱点は、API Levelが高すぎること。

3の場合:

互換ライブラリがあれば、Android1.6から使える。
利点は、どこでもアクティビティのライフサイクルに載せられること。
弱点は、なんか無駄にくせがあること。あとドキュメントがさっぱりなこと。

ってことで、今なら、3が便利っぽいので3でやる場合の基本とノウハウ(?っていうのかな)を書いてみる。
いつも通り基本的なのは軽く流しちゃうけどっ。

〜定義編〜

DialogFragmentは抽象クラスじゃないけど、継承して使うの。
基本は、onCreateDialogをオーバーライドすればいいかな。
onCreateViewなんかもあるけどその辺は別にどうでもいいや(マテ)。

〜使用編〜

DialogFragmentのshowメソッドを使いましょう。
おわり。

簡単だよね!(゚ー゚)(。_。)(゚-゚)(。_。)ウンウン
……というのが一般的な説明な気がする。

Fragmentじゃない時のコードからの移行も簡単だよみたいになっているけど、表面上はって感じかな。
実際にアプリ作ってる側からすると、きっつぃ。
以下は、その辺の紹介だよ。

〜動的なパラメータ〜

Bundleを渡せそうなメソッドにsetArgumentがあるから、これ使えば良さそう。Javadocでもそんな感じだし。
ただ、onPrepareDialogみたいなのがないの!onCreateDialogしかないの!
Activityの時のキャッシュみたいな機能はなくなったのかな。それっぽい解説が全くないんだよね。
一応、動作としては毎回呼ばれるみたいだけど、onCreateDialogの中でgetArgumentするってことでいいのかな。
移行用ドキュメントちゃんと作ってほしいなぁ。それともわたしが読み飛ばしちゃってるのかしら。
むー(・x・

〜キャンセルリスナー〜

onCreateDialogあたりで、作ったダイアログにリスナーを登録する。
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
  @Override public void onCancel(DialogInterface dialog) {
    // do something
  }
});

こんな感じかな。動かしてみると……、はい、普通に呼ばれないね。
移行するとこんなのでいきなり躓くし。
なんか、DialogFragment#onCancelの方をオーバーライドしないとダメっぽい。

〜複数回のdismiss〜

ちょっと複雑なProgressDialogなんかを作る場合に起こりそう、っていうか起こったんだけど、
複数回DialogFragment#dismissを呼ぶと落ちる。

サンプルコードはこんなかんじ!
this.df.dismiss();
this.df.dismiss(); // 落ちる。
落ち方はこんなかんじ
Caused by: java.lang.NullPointerException
  at android.support.v4.app.DialogFragment.dismissInternal(DialogFragment.java:163)
  at android.support.v4.app.DialogFragment.dismiss(DialogFragment.java:149)

う〜みゅ、そのままだね!あ、いや、別に連続して書いてはいないけどね。
複数スレッドからダイアログを閉じたいだけなんだけど……。
Dialogの時は起きないのに。まったく……(゜▽、゜
ストリームとかだって複数回closeとか出来るようにするでしょう。普通……。
というわけで?以下のようにして解決。

this.df.onDismiss(this.df.getDialog());
this.df.onDismiss(this.df.getDialog()); // 落ちない。

まぁ、詳細は、DialogFragmentのソースコードでも見てください。二つのメソッドの実装とコメントを見れば一発かな。
実装依存なコーディングだからあまり良くないんだろうだけど、互換ライブラリだし、まぁ、いいかなって。
ていうか、dismiss呼ぶので落ちるのは個人的にイヤなんだんだけど……。
onDismissの実装見る限り、わざとやってるように見えるんだけど、どうしてなのかなぁ……。

全体的にFragment作るのに忙しくて互換性がぽいぽいっとされた感じ。
ま、いつものGoogleさんっぽいけど、これからもこういう感じなんだろうね。
だいじょうぶなのかな〜いろんな意味で(笑)

タグ:android
posted by すふぃあ at 19:47| Comment(3) | TrackBack(0) | 雁字