ViewPager2/Tabs problem with ViewModel state

浪尽此生 提交于 2020-02-29 13:21:13

问题


I am following the MVVM pattern - meaning I have a ViewModel for each Fragment.

I added two tabs by using ViewPager2.

My adapter looks like this:

@Override
public Fragment createFragment(int position) {
    switch (position) {
        case 0:
            return new MergedItemsFragment();
        case 1:     
            return new ValidatedMergedItemsFragment();
    }
    return new MergedItemsFragment();
}

The tabs are working. However, I noticed that the ViewModel of my MergedItemsFragment is behaving weirdly. Before I added tabs I navigated to the Fragment like this:

NavHostFragment.findNavController(this).navigate(R.id.action_roomFragment_to_itemsFragment);

When I left that fragment with NavHostFragment.findNavController(this).popBackStack() and later on returned to that fragment I would get a new empty ViewModel. This was intended.

With the new approach I am navigating with return new MergedItemsFragment(). When I leave that fragment and later on return I am getting a ViewModel that contains the old data. That is an issue because the old data is not relevant anymore because the User selected different data in another fragment.


Update #1

I realized that he actually keeps all the old Fragments in memory because the same print statements gets called multiple times. The times it is called increases with the amount of times I leave and return to that screen. So if I leave and return 10 times and rotate my device he will actually execute one line 10 times. Any guesses how to implement Tabs/ViewPagers with Navigation Components in a manner that works with ViewModels?


Update #2

I set my ViewModels like this:

viewModel = new ViewModelProvider(this, providerFactory).get(MergedItemViewModel.class)

I get the same results with:

viewModel = ViewModelProviders.of(this).get(MergedItemViewModel.class);

I bind the ViewModel in the Fragment itself. Therefore, this is the Fragment.


回答1:


As per your comment, you are using Fragment and inside that Fragment there is your viewpager. So while creating your Adapter for ViewPager you need to pass childFragmentManager instead of getActivity()

Below is a sample Adapter for your viewPager that you can use

class NewViewPagerAdapter(fm: FragmentManager, behavior: Int) : FragmentStatePagerAdapter(fm, behavior) {
    private val mFragmentList: MutableList<Fragment> = ArrayList()
    private val mFragmentTitleList: MutableList<String> = ArrayList()

    override fun getItem(position: Int): Fragment {
        return mFragmentList[position]
    }

    override fun getCount(): Int {
        return mFragmentList.size
    }

    fun addFragment(fragment: Fragment, title: String) {
        mFragmentList.add(fragment)
        mFragmentTitleList.add(title)
    }

    override fun getPageTitle(position: Int): CharSequence? {
        return mFragmentTitleList[position]
    }
}

and while creating your adapter call it like

   val adapter = NewViewPagerAdapter(
        childFragmentManager,
        FragmentPagerAdapter.POSITION_UNCHANGED
    )

as if you see the documentation for FragmentStatePagerAdapter it states that you should pass (FragmentManager, int) inside your adapter's constructor

I hope this will solve your issue as I was facing the same issue one day.

Happy coding.



来源:https://stackoverflow.com/questions/60129178/viewpager2-tabs-problem-with-viewmodel-state

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!