タブ切り替えによる画面表示で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でページを切り替えたタイミングでの処理を実現することができます。