BottomNavigationViewのタブで切り替え表示をするFragmentのうちの1つで
ViewPagerを使って実装をしていて
BottomNavigationViewのタブを切り替えると実行されるはずの読み込み処理が実行されず、かつ直前に読み込んでいたデータも表示されなくなった
という現象が起きて嵌りました。
【画面構成(階層)】
MainActivity(BottomNavigationViewを使用)
|- ParentFragment(ViewPagerを使用)
|- ViewPager
|- ChildFragments(ViewPagerの各ページに表示するFragment達)
先に解決策の載せておきます。↓↓
解決策
ViewPagerにセットするFragmentPagerAdapterのインスタンスを生成する時に
childFragmentManager
を渡す。これで解決しました。
val adapter = FragmentPagerAdapter(childFragmentManager) //← ここ
viewPager.adapter = adapter
class AroundPagerAdapter(fragmentManager: FragmentManager?) :
FragmentPagerAdapter(fragmentManager) {
// 省略
}
val adapter = FragmentPagerAdapter(fragmentManager)
viewPager.adapter = adapter
class AroundPagerAdapter(fragmentManager: FragmentManager?) :
FragmentPagerAdapter(fragmentManager) {
// 省略
}
実際に起きていたこと
BottomNavigationViewのタブから別タブに切り替えて再びそのタブに戻ってきたとき、
FragmentPagerAdapter#getItem()
が呼ばれず、 ViewPager 内が再読込みされない現象が起きていました。
なぜ起きたのか、、、
①FragmentPagerAdapterはメモリ上にViewPagerの子Fragment(ChildFragments)を全て保持する
→ タブを切り替えた時は以前のものが再利用される
FragmentPagerAdapter
②BottomNavigationViewのタブ切り替えだとParentActivityは生きたまま
→ FragmentManagerはViewPager内の子Fragment達(ChildFragments)を保持したままになり、 FragmentPagerAdapter#getItem() が呼ばれない
①②に対して、childFragmentManagerを使うと
保持される ViewPager 内のChildFragmentsはParentFragmentのFragmentManagerで管理される。
→タブを切り替えたときにはParentFragmentのインスタンスを再生成するのでそのタイミングでFragmentManagerがリセットされる
→新しくChildFragmentsのインスタンスを生成するので「FragmentPagerAdapter#getItem()」 が呼ばれて再読込みが始まるようになる。
(余談)
ViewPager のスワイプが起きたときは ParentFragment が生きている限り、 FragmentManager 内で ChildFragments が管理されるので、通常通り効率的にスワイプできるようになる。
まとめ
かなり嵌りましたが、解決してみるとあっけなかったですね 笑
以上です。