タブ切り替えによる画面表示でViewPager + FragmentPagerAdapterを使ったので、そのときに調査した部分を共有します。
問題
ViewPagerでFragmentを切り替える処理を実装するときに、Fragmentが表示されたタイミングで実行したい処理があるとします。
Fragmentのライフサイクルの中にあるonResumeなどで処理を実行しても良さそうですが、Fragmentが表示されたタイミングで次に遷移可能な隣のFragmentも同時に生成されてしまうので、この方法だとうまくいきません。
例えば2ページ目に遷移したとします。
I/SampleAdapter(24960): getItem[3]
I/SampleFragment(24960): <init>:[0]
I/SampleFragment(24960): onCreate:[3]
I/SampleFragment(24960): onCreateView:[3]
I/SampleFragment(24960): onResume:[3]
この場合は、2ページ目への遷移と同時に3ページ目のFragmentを準備するための処理が動くために、この時点で3ページ目のFragmentのonResumeまで呼ばれてしまいます。
ViewPager+FragmentPagerAdapterにおけるFragmentのライフサイクル
解決策
FragmentPagerAdapterのコンストラクタにBEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENTというフラグを渡します。
ちなみに、これまではFragment表示時のイベント実行にsetUserVisibleHintが使えていたのですが、fragment-1.1.0-alpha07でdeprecatedになりました。
class SampleAdapter(fm: FragmentManager) :
FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment {
return SampleFragment.newInstance(position)
}
override fun getCount(): Int {
// ...
}
}
BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENTを指定することで、呼び出される側のFragmentがオンスクリーンになったタイミングでonResumeが呼ばれるように制御することができるようになります。
残りの表示されていないFragmentは、onStartまで進んでいる状態です。
呼び出される側のFragmentはこんな感じです。
class SampleFragment : Fragment() {
// ...
override fun onResume() {
super.onResume()
// オンスクリーン時に実行したい処理
}
// ...
companion object {
fun newInstance(position :Int): SampleFragment {
return SampleFragment()
}
}
}
あとはFragmentのonResumeにFragmentが表示されたときに実行したい処理を書けば、ViewPagerでページを切り替えたタイミングでの処理を実現することができます。