ViewModel状态的ViewPager2 / Tabs问题 [英] ViewPager2/Tabs problem with ViewModel state

查看:274
本文介绍了ViewModel状态的ViewPager2 / Tabs问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循MVVM模式-意味着每个片段都有一个ViewModel。



我使用ViewPager2添加了两个标签。 / p>

我的适配器如下:

  @Override 
public Fragment createFragment(int position){
switch(position){
case 0:
return new MergedItemsFragment();
情况1:
返回new ValidatedMergedItemsFragment();
}
返回新的MergedItemsFragment();
}

选项卡正在运行。但是,我注意到我的MergedItemsFragment的ViewModel行为异常。
在添加选项卡之前,我像这样导航到片段:

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

当我用 NavHostFragment.findNavController(this).popBackStack( ),然后返回该片段,我将得到一个新的空ViewModel。 这是有意的。



使用新方法,我使用导航新的MergedItemsFragment()。当我离开该片段并稍后返回时,我得到一个包含旧数据的ViewModel。这是一个问题,因为旧数据不再相关,因为用户在另一个片段中选择了不同的数据。






Update# 1



我意识到他实际上将所有旧的碎片保留在内存中,因为相同的打印语句被称为多个次。它的调用时间随着我离开并返回该屏幕的次数而增加。因此,如果我离开并返回10次并旋转设备,他实际上将执行10次一行。 有人猜测如何以与ViewModels兼容的方式来实现带有导航组件的Tabs / ViewPagers吗?






Update#2



我将ViewModels设置如下:

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

我得到的结果与此相同:

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

我将ViewModel绑定在Fragment本身中。因此,是片段。

解决方案

根据您的评论,您正在使用Fragment,并且在Fragment中有您的viewpager。
因此,在为ViewPager创建适配器时,您需要传递 childFragmentManager 而不是 getActivity()



以下是适用于您的viewPager的示例适配器,您可以使用

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

重写fun getItem(position:Int):片段{
return mFragmentList [position]
}

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

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

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

在创建适配器时将其命名为

  val adapter = NewViewPagerAdapter(
childFragmentManager,
FragmentPagerAdapter.POSITION_UNCHANGED

就像您看到 FragmentStatePagerAdapter 的文档一样我应该在适配器的构造函数中传递(FragmentManager,int)



我希望这可以解决您的问题,因为我面临着同样的问题



快乐编码。


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.

解决方案

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.

这篇关于ViewModel状态的ViewPager2 / Tabs问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆