我已经花了一些时间来解决这个问题,并且我已经为任何需要听到它的人诊断了这个问题。我试图让我的解决方案尽可能传统。如果我们看看你的陈述:
因此,当我导航回 HomeFragment 时,将重新创建适配器,这也会重新创建 Viewpager2 中的所有片段,并且当前项目重置为 0。
问题是当前项目被重置为 0,因为您的适配器所基于的列表被重新创建。为了解决这个问题,我们不需要保存适配器,只需要保存其中的数据。考虑到这一点,解决问题一点也不难。
让我们布局一些定义:
HomeFragment
是,正如你所说,你的主机ViewPager2
,
MainActivity
是正在运行的活动,其中托管HomeFragment
和所有创建的片段
- 我们正在通过 的实例进行分页
MyFragment
。您甚至可以拥有不止一种类型的片段来进行分页,但这超出了本示例的范围。
PagerAdapter
是你的FragmentStateAdapter
,它是HomeFragment
's的适配器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
. 创建一个“视图模型”:
/* 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
...
}
...
}