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”

http://stackoverflow.com/questions/12105064/actions-in-onactivityresult-and-error-can-not-perform-this-action-after-onsavei

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のリプレイスは、思う以上に手間がかかりますよ…と。単純な置換に留まらないとあらかじめ認識していれば、落ち着いて対処できると思いますわ。