我已经花了一些时间来解决这个问题,并且我已经为任何需要听到它的人诊断了这个问题。我试图让我的解决方案尽可能传统。如果我们看看你的陈述:
因此,当我导航回 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
...
}
...
}