gpt4 book ai didi

android - Viewpager2 带有 fragment 和 Jetpack 导航 : Restore fragments instead of recreating them

转载 作者:行者123 更新时间:2023-12-03 07:29:31 24 4
gpt4 key购买 nike

我有一个 Viewpager2Fragment 内(我们称之为 HomeFragment )。那Viewpager本身也包含 Fragments .当我离开 HomeFragment它的 View 将被破坏,当我返回时, View 将被重新创建。现在我设置Viewpager2的适配器在 HomeFragment onViewCreated()期间.因此,当我导航回 HomeFragment 时,将重新创建适配器。 ,这也重新创建了所有 FragmentsViewpager2并且当前项目重置为 0。如果我尝试重新使用我在第一次创建 HomeFragment 时实例化的适配器我得到了一个异常(exception),因为在 FragmentStateAdapter 内部进行了这项检查:

public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
checkArgument(mFragmentMaxLifecycleEnforcer == null);

有人知道我如何在返回时防止重新创建所有内容吗?否则这是一个相当大的性能开销并阻碍了我的用户体验。

最佳答案

我已经花了一些时间来解决这个问题,并且我已经为任何需要听到它的人诊断了这个问题。我试图让我的解决方案尽可能传统。如果我们看看你的陈述:

Therefore the adapter will be recreated when I navigate back to theHomeFragment, which also recreates all Fragments in the Viewpager2 andthe current item is reset to 0.


问题是当前项目被重置为 0,因为您的适配器所基于的列表被重新创建。要解决此问题, 我们不需要保存适配器,只需要保存其中的数据。 考虑到这一点,解决问题一点也不难。
让我们布局一些定义:
  • HomeFragment正如您所说,是您的ViewPager2 的主机。 ,
  • MainActivity是托管 HomeFragment 的正在运行的 Activity 以及其中所有创建的 fragment
  • 我们正在通过 MyFragment 的实例进行分页。 .您甚至可以拥有不止一种类型的 fragment 来进行分页,但这超出了本示例的范围。
  • PagerAdapter是你的FragmentStateAdapter ,这是 HomeFragment 的适配器的ViewPager2 .

  • 在本例中, MyFragment有构造函数 constructor(id : Int) .然后, PagerAdapter可能会如下所示:
    class PagerAdapter(fm : Fragment) : FragmentStateAdapter(fm){

    var ids : List<Int> = listOf()

    ...

    override fun createFragment(position : Int) : Fragment{
    return MyFragment(ids[position])
    }


    }
    我们面临的问题是每次重新创建 PagerAdapter构造函数被调用并且构造函数,正如我们在上面看到的,设置 ids到一个空列表。
    我的第一个想法是也许我可以切换 fm成为 MainActivity .我没有导航出 MainActivity所以我不知道为什么,但这个解决方案不起作用。
    相反,您需要做的是从 PagerAdapter 中提取数据。 .创建一个“ View 模型”:
        /* We do NOT extend ViewModel. This naming just indicates that this is your data- 
    storage vehicle for PagerAdapter*/
    data class PagerAdapterViewModel(
    var ids : List<Int>
    )
    然后,在 PagerAdapter ,进行以下调整:
    class PagerAdapter(
    fm : Fragment,
    private val viewModel : PagerAdapterViewModel
    ) : FragmentStateAdapter(fm){

    // by creating custom getters and setters, you are migrating your code to this
    // implementation without needing to adjust any code outside of the adapter
    var ids : List<Int>
    get() = viewModel.ids
    set(value) {viewModel.ids = value}

    override fun createFragment(position : Int) : Fragment{
    return MyFragment(ids[position])
    }


    }
    最后,在 HomeFragment ,你会有类似的东西:
    class HomeFragment : Fragment(){ 

    ...

    /** Calling "by lazy" ensures that this object is only created once, and hence
    we retain the data stored in it, even when navigating away. */
    private val pagerAdapterViewModel : PagerAdapterViewModel by lazy{
    PagerAdapterViewModel(listOf())
    }

    private lateinit var pagerAdapter : PagerAdapter

    ...

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    ...
    pagerAdapter = PagerAdapter(this, pagerAdapterViewModel)
    pager.adapter = pagerAdapter
    ...
    }

    ...

    }

    关于android - Viewpager2 带有 fragment 和 Jetpack 导航 : Restore fragments instead of recreating them,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57271553/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com