実装方法によっては発生しないのかもしれないけれど、自分の開発状況下で発生している問題について。
結論
子フラグメントをバックスタックから復元することはできる。しかし色々変更しすぎてもはや何が決め手になったかよくわからず。以下は本結論に繋がらない別な話である。
課題
あるFragment内に子フラグメントのViewまたはViewPagerを設置し、親フラグメント側のViewの画面遷移を行った際、バックボタン押下で前画面に戻った際に子フラグメントが再描画されず真っ白になる。できれば遷移前の状態を再現したい。
対応
あれこれ調べた結果、現時点では親のFragmentManagerでは子Viewの状態までは再現してくれない模様。なのでスクロールなどの細かな表示状態はともかく、再描画だけは行わせることにする。
子Fragmentの場合
親フラグメントのonCreateViewで子Fragmentが設置済みかを確認し、設置前ならadd、設置済みならreplaceする。FragmentManagerはgetChildFragmentManager()を使って取得。
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final FragmentManager cfm = getChildFragmentManager(); Fragment f = cfm.findFragmentById(R.id.childFragmentContainer); FragmentTransaction ft = cfm.beginTransaction(); if (f == null) { ft.add(R.id.childFragmentContainer, new Fragment(), "child"); } else { ft.replace(R.id.childFragmentContainer, new Fragment(), "child"); } ft.commit(); ... }
ViewPagerの場合
ViewPagerは内部でフラグメント管理を独自に行うため上記の方法が利用できない。しかしながら放っておくと描画に失敗するので古いデータが無いと思わせる必要がある。具体的にはPagerAdapterのrestoreStateを無視する
public class MyPagerAdapter extends FragmentStatePagerAdapter { @Override public void restoreState(Parcelable state, ClassLoader loader) { // super.restoreState(state, loader); // 何もしない!! } }
こうすると常にFragmentの再生成、再描画が行われ、空白のビューを見せられることはなくなる。
本当に辿り着きたかったゴールは前回表示状態の再現なのだけど、まあ仕方ない。