- class MainActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- val pager: ViewPager = findViewById(R.id.pager)
- pager.adapter = MyPagerAdapter(supportFragmentManager)
- }
- class MyPagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
- override fun getItem(position: Int): Fragment {
- return PageFragment.newInstance(position)
- }
- override fun getCount(): Int {
- return 10
- }
- }
- }
(FragmentPagerAdapter では一度作った Fragment インスタンスは保持されます)
そのため各ページの Fragment 内で ViewModel を取得するときに、以下のように ViewModelProviders.of() にその Fragment のインスタンスを指定してしまうと、 再度そのページが必要になったときに ViewModel も新しく作り直されてしまいます。
- class PageFragment : Fragment() {
- ...
- override fun onActivityCreated(savedInstanceState: Bundle?) {
- super.onActivityCreated(savedInstanceState)
- val viewModel = ViewModelProviders.of(this)
- .get(PageViewModel::class.java)
- val position = arguments!!.getInt("position")
- Log.d("PageFragment", "$position : $viewModel")
- }
- companion object {
- fun newInstance(position: Int): PageFragment {
- return PageFragment().apply {
- arguments = Bundle().apply {
- putInt("position", position)
- }
- }
- }
- }
- }
D/PageFragment: 0 : net.yanzm.sample.PageViewModel@2dc8dc7
D/PageFragment: 1 : net.yanzm.sample.PageViewModel@389f31d
D/PageFragment: 2 : net.yanzm.sample.PageViewModel@60a3f63
D/PageFragment: 3 : net.yanzm.sample.PageViewModel@ad7a419
D/PageFragment: 0 : net.yanzm.sample.PageViewModel@8d76ebf ← 2dc8dc7 ではなく、別のインスタンスが来てしまう
そこで ViewModelProviders.of() に ViewPager を持つ Activity を指定すると、ViewModel のインスタンスが Activity にひも付くので、 ViewPager のページ移動で Fragment が作り直されても ViewModel は以前のインスタンスが取れるようになります。
- val viewModel = ViewModelProviders.of(activity)
- .get(PageViewModel::class.java)
D/PageFragment: 0 : net.yanzm.focussample.PageViewModel@a704306
D/PageFragment: 1 : net.yanzm.focussample.PageViewModel@a704306
D/PageFragment: 2 : net.yanzm.focussample.PageViewModel@a704306
D/PageFragment: 3 : net.yanzm.focussample.PageViewModel@a704306
D/PageFragment: 0 : net.yanzm.focussample.PageViewModel@a704306
各ページで別の ViewModel インスタンスを使いたいので、ViewModel のインスタンスを取得するときにキーを指定するようにします。
- val position = arguments!!.getInt("position")
- val viewModel = ViewModelProviders.of(activity)
- .get(position.toString(), PageViewModel::class.java) // position をキーとして指定
D/PageFragment: 0 : net.yanzm.focussample.PageViewModel@a704306
D/PageFragment: 1 : net.yanzm.focussample.PageViewModel@2dc8dc7
D/PageFragment: 2 : net.yanzm.focussample.PageViewModel@a052ff4
D/PageFragment: 3 : net.yanzm.focussample.PageViewModel@389f31d
D/PageFragment: 0 : net.yanzm.focussample.PageViewModel@a704306 ← 同じ a704306 が返ってきている。
ViewPager を持っているのが Fragment の場合は、parentFragment を指定すれば ViewModel を ViewPager を持っている Fragment にひも付けることができます。
- val position = arguments!!.getInt("position")
- val viewModel = ViewModelProviders.of(parentFragment!!)
- .get(position.toString(), PageViewModel::class.java) // position をキーとして指定
0 件のコメント:
コメントを投稿