Androidアプリで support library v4 を使用している場合、ライブラリの revision によっては、ネストされている子フラグメントが画面回転等の際に失われてしまう問題があるようです。
画面回転等で Activity が再生成される場合でもフラグメントのインスタンスを保持しておくよう、setRetainInstance(true) の指定を行うことがありますが、そのようなフラグメントがネストされた子フラグメントを持つ場合、Activity 再生成のタイミングで子フラグメントが失われてしまう場合があるようです。
この問題は support library v4 の rev.20 から発生しているようで、Fragment クラスで保持している ChildFragmentManager 自体が失われてしまうといったことが起きているようです。 ( 現時点の最新版である rev.22.1.1 でも解消されていない模様。 )
Issue Tracker でこの件についてサンプル対処コード添えてコメントされている方が、自身のブログでもこの問題について言及されていました。
以下、リンク先からの引用コードです。
public class NestingFragment extends Fragment{ //As we setRetainInstanceState(true), this field will hold //the reference of the old ChildFragmentManager private FragmentManager mRetainedChildFragmentManager; @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setRetainInstance(true); } @Override public void onAttach(Activity activity) { super.onAttach(activity); if (mRetainedChildFragmentManager != null) { //restore the last retained child fragment manager to the new //created fragment try { Field childFMField = Fragment.class.getDeclaredField("mChildFragmentManager"); childFMField.setAccessible(true); childFMField.set(this, mRetainedChildFragmentManager); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } else { mRetainedChildFragmentManager = getChildFragmentManager(); } } }
フラグメントがアクティビティに attach された際に ChildFragmentManager の参照を保持しておき、再生成の際にその参照をリフレクションで直接フィールドに書き戻しているようです。
本来ならアクセスできないフィールドにアクセスするコードであるため、環境によって動作しない可能性や今後フィールド名の変更等により動作しなくなる恐れもありますが、とりあえず今回はこのコードを参考にさせて頂き、自身で作成している基底フラグメントにこのようなコードを実装することでこの問題を回避することにしました。
最近になってようやく Android アプリの本格的な開発に携わるようになったのですが、経験が浅いためちょっと凝ったことをしようとすると色々と難しい問題に直面しますね。