FragmentPagerAdapter の getItem() で返す Fragment に次のようにログを入れました。
class SimpleFragment : Fragment() {
override fun onStart() {
super.onStart()
println("$position : onStart")
}
override fun onResume() {
super.onResume()
println("$position : onResume")
}
override fun onPause() {
super.onPause()
println("$position : onPause")
}
override fun onStop() {
super.onStop()
println("$position : onStop")
}
}
1. レイアウトより前のタイミング(例えば onCreate())で adapter をセットしている場合
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewPager.adapter = MyPager(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
}
}
この場合、ログは次のようになります。
System.out: 0 : onStart
System.out: 1 : onStart
System.out: 0 : onResume
つまり
- 1. position 0 の Fragment の onStart()
- 2. position 1 の Fragment の onStart()
- 3. position 0 の Fragment の onResume()
2. レイアウトより前のタイミング(例えば onCreate())で adapter をセットし、currentItem を変更している場合
onCreate() で ViewPager に adapter をセットした後 currentItem を 1 にしてみます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewPager.adapter = MyPager(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
viewPager.currentItem = 1
}
}
この場合のログはこうなります。
System.out: 1 : onStart
System.out: 0 : onStart
System.out: 2 : onStart
System.out: 1 : onResume
つまり
- 1. position 1 の Fragment の onStart()
- 2. position 0 の Fragment の onStart()
- 3. position 2 の Fragment の onStart()
- 4. position 1 の Fragment の onResume()
3. レイアウトより後のタイミングで adapter をセットしている場合
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Handler().postDelayed(
{
viewPager.adapter = MyPager(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
},
1000
)
}
}
onCreate() から1秒後に adapter をセットしてみます。この場合ログは次のようになります。
System.out: 0 : onStart
System.out: 1 : onStart
System.out: 0 : onResume
「1. レイアウトより前のタイミング(例えば onCreate())で adapter をセットしている場合」と同じですね。
- 1. position 0 の Fragment の onStart()
- 2. position 1 の Fragment の onStart()
- 3. position 0 の Fragment の onResume()
4. レイアウトより後のタイミングで adapter をセットし、currentItem を変更している場合
onCreate() から1秒後に adapter をセットし、currentItem を 1 にしてみます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Handler().postDelayed(
{
viewPager.adapter = MyPager(supportFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
viewPager.currentItem = 1
},
1000
)
}
}
この場合ログは次のようになります。
System.out: 0 : onStart
System.out: 1 : onStart
System.out: 0 : onResume
System.out: 2 : onStart
System.out: 0 : onPause
System.out: 1 : onResume
「2. レイアウトより前のタイミング(例えば onCreate())で adapter をセットし、currentItem を変更している場合」と同じになりません!
まず「3. レイアウトより後のタイミングで adapter をセットしている場合」と同じことが起こります。
つまり
- 1. position 0 の Fragment の onStart()
- 2. position 1 の Fragment の onStart()
- 3. position 0 の Fragment の onResume()
その後
- 4. position 2 の Fragment の onStart()
- 5. position 0 の Fragment の onPause()
- 6. position 1 の Fragment の onResume()
adapter をセットしたタイミングで 1 〜 3 までの流れが起こり、currentItem を 1 にしたタイミングで 4 〜 6 の流れが起こります。
このように、レイアウトよりも後のタイミングで adapter をセットすると、その時点で position 0 の Fragment を PrimaryItem として onResume() まで呼ばれてしまいます。
そのため、レイアウトよりも後のタイミングで adapter をセットして currentItem を 0 以外に変更する場合、「Fragment がユーザーに表示されたタイミングで xx したい」処理のトリガーとして onResume() を使うには注意が必要です。
adapter がセットされている間の onResume() に反応してしまうと、その後 currentItem が変更されて実際にはユーザーにはほぼ見えない Fragment でも処理が走ってしまうため、adapter がセットされている間だけフラグを立てておいて onResume() で反応しないような工夫が必要になります。