showDialogメソッドの呼び出しを無くす。
Android 2系の環境で製作してきたアプリを 4系に移行しようとしたところ、showDialogの問題に悩まされました。一言で言えば、「互換パッケージを利用して、アクティビティの継承元を FragmentActivityに変更して、DialogFragmentを使用すれば良い」ということです。いろいろな人が記事を書いているので、まずはリンクを貼ります。
▽ startActivityForResult
Android Support Package の Fragment から startActivityForResult() を使うときの注意点
http://y-anz-m.blogspot.jp/2012/05/support-package-fragment.html
Fragmentインスタンスの startActivityForResultメソッドを使うと危険らしい。getActivityメソッドから Activityインスタンスを取得して、そのstartActivityForResultメソッドを呼び出すことにした。
▽ setCancelable
DialogFragmentではsetCancelableはフラグメントに対して行う
http://smartphone-zine.com/mobile/android/dialogfragment-setcancelable.html
DialogFragmentメソッドのsetCancelableメソッドを使用する
▽ Activityのライフサイクルとの兼ね合い
Actions in onActivityResult and “Error Can not perform this action after onSaveInstanceState”
Activityの遷移後に元のアクティビティに戻るタイミングでの DialogFragment表示時に IllegalArgumentExceptionが発生する場合の対処法。
▽ setOnCancelListener
コジオニルク - Android - DialogFragment
http://www.kojion.com/android/dialog_fragment.html
DialogFragmentクラスのsetOnCancelListenerが上手く動作しないようなので、DialogFragmentクラスの onCancelメソッドをオーバーライドして、そこに処理を移す。
▽ dismiss
コジオニルク - Android - DialogFragment
http://www.kojion.com/android/dialog_fragment.html
DialogFragmentインスタンスに対して 2回 dismissメソッドを実行すると落ちるらしい。これは実験していないので不明なのだけど、アプリ側と UI側から同時に dismissをしたりすと不味いだろうということで、以下の方法があるらしい。直接 onDissmissメソッドを呼んでやるということみたい。
this.dialogFragment.onDismiss(this.dialogFragment);
▼ 別の対処法?
ただ、直接呼び出すのも気持ち悪いしなあ…と思って、僕は以下のように実装しました。
try{
this.dialogFragment.dismiss();
} catch(NullPointerException e);
// 何もしない
}
ところが、これが別の不具合を発生させたということで、それがこの記事を書いた目的。分かる人には簡単に分かる、Javaの基本的な問題…ですわ。
これで、dismissメソッド内の実装で NullPointerExceptionが発生しても問題なく処理できるようになるのだけれど、だけれど、…それ以前に、this.dialogFragmentが nullだったとき、dismissメソッドの呼び出し前に発生する NullPointerExceptionまで問題なくなってしまって、コーディングの不具合をスルーしてしまいました…わ。両者が発生する例外が、ともに NullPointerExceptionなので区別がつかない、というところが…ね。
今回は、もう書いてしまったのでこのまま放置だけれど、次からは以下のように書こうと思いますわ。
if(this.dialogFragment == null) {
throw new NullPointerException();
} else {
try{
this.dialogFragment.dismiss();
} catch(NullPointerException e);
// 何もしない
}
}
でも…ここまで長くなると、onDismissを呼んだほうがシンプルすっきりの気がしてきますね。
ともかく、showDialogのリプレイスは、思う以上に手間がかかりますよ…と。単純な置換に留まらないとあらかじめ認識していれば、落ち着いて対処できると思いますわ。