Problem while using multiple instance of same Fragment with same ViewModel in Viewpager

Viewed 2227

I am having a Fragment (FRAG1) with a View Model (VM1). I am creating two new instances of this fragment in a FragmentPagerAdapter to load inside a ViewPager.

The Viewpager is present inside a parent Fragment.

The ViewModels in both the instance of the fragment doesn't seem to be unique. Both the fragment instances seems to have the properties of the ViewModel instance created in the second fragment which is initialized last.

private inner class ItDeclarationFragAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm)
{
    override fun getItem(position: Int): Fragment
    {
        return when (position)
        {
            0 -> ITDeclarationSummaryFragment.newInstance(false)
            1 -> ITDeclarationSummaryFragment.newInstance(true)

            else -> ITDeclarationSummaryFragment.newInstance(false)
        }
    }

    override fun getCount(): Int
    {
        return 2
    }

    override fun getPageTitle(position: Int): CharSequence?
    {
        return when (position)
        {
            0 -> resources.getString(R.string.zpl_itDeclaration_tile)
            1 -> resources.getString(R.string.zpl_itDeclaration_poi_title)

            else -> resources.getString(R.string.zpl_reimbursements_summary)
        }
    }
}

The Fragment creates new creates an instance of the ViewModel in OnCreate()

override fun onCreate(savedInstanceState: Bundle?)
{
    super.onCreate(savedInstanceState)

    vm = ViewModelProvider.AndroidViewModelFactory.getInstance(activity!!.application).create(ITDeclarationSummaryViewModel::class.java)
    vm.setRepository(getRepo())
    vm.mIsPOI = arguments!![StringConstants.isPOI]!! as Boolean
}

It is later set to Binding on OnCreateView()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
{
    mView = inflater.inflate(R.layout.declaration_summary_fragment, container, false)

    mBinding       = DeclarationSummaryFragmentBinding.bind(mView!!)
    mBinding.model = vm
    mBinding.setLifecycleOwner(this)

    return mBinding.root
}

But the view models in both the fragments seem to retain the values of the second fragment. They don't seem to be separate and unique.

For Example,

There is a Boolean in the view model which is FALSE in first ViewModel and TRUE in the second one. But once the second VM is created both the fragment view model will be TRUE.

Similarly, the observers of the LiveData in first ViewModel don't work.

Please help me solve this. Thanks in advance.

2 Answers

The thing is you are creating ViewModels with AndroidViewModelFactory, which holds the same instance for all view models, if you are using the same view model in all fragments. Maybe consider creating view models by calling:

ViewModelProviders.of(fragment).get(ViewModel.class)

This will always give you a new instance of view model per fragment. Or If you want to hook on same activity, just pass instead of fragment, activity.

The problem is not because of Fragment or View Model.

The view models hold an instance or a Repository class. I have by mistake supplied the same instance of the Repository class to both the ViewModels.

This caused the data to persist across ViewModels.

Related