2013/01/28

Android:DialogFragment.setRetainInstance(true)使用時は画面回転に注意


DialogFragmentにsetRetainInstance(true)を指定する時は注意が必要です。
下記の手順を踏むと、表示中のダイアログが閉じてしまいます。

【手順】
 1. DialogFragmentを生成し、setRetainInstance(true)を指定
 2. DialogFragmentを.show(...)メソッドで表示
 3. 画面の向きを変更する(Orientation change)

【結果】
手順2で表示したダイアログが閉じてしまいます(画像1)。
しかし、setRetainInstance(false)を設定している場合ダイアログは閉じません(画像2)。
画像1:setRetainInstance(true)

画像2:setRetainInstance(false)


setRetainInstance(true)の場合でもダイアログを閉じたくなければ、次の回避策を使います。
# コードが汚れる上に力技です。

【回避策】
onDestroyView()でsuper.onDestroyView()をコールする前に、ダイアログが持つDismissメッセージをnull化します。
@Override
public void onDestroyView() {
    if (getDialog() != null && getRetainInstance())
        getDialog().setDismissMessage(null);
    super.onDestroyView();
}
ダイアログが閉じる原因はOrientation changeによるDialogFragmentのonDestroyViewで、
Dialog.dismiss()によりメッセージキューにpushされたDISSMISSメッセージが、onCreateView後に再活性化されるためです。
この結果、ダイアログは表示された直後にdismissされてしまいます。

回避策の内容は、Orientation changeによるonDestroyViewでは、Dismissメッセージをnull化して投げさせない対応となります。

以上です。