我花了一些时间研究了这个问题,并为需要听到的人诊断了问题。我尽可能地保持了我的解决方案传统。如果我们看一下你的陈述:
因此,当我导航回HomeFragment时,适配器将被重新创建,这也会重新创建Viewpager2中的所有片段和当前项目将重置为0。
问题在于当前项目被重置为0,因为适配器所基于的列表被重新创建了。为了解决这个问题,我们不需要保存适配器,只需要保存其中的数据即可。有了这个想法,解决问题并不难。
让我们列出一些定义:
HomeFragment
是你的 ViewPager2
宿主,正如你所说的。
MainActivity
是运行活动,它是 HomeFragment
和其中所有创建的片段的宿主。
- 我们正在浏览
MyFragment
的实例。您甚至可以浏览多种类型的片段,但这超出了本示例的范围。
PagerAdapter
是 HomeFragment
的 ViewPager2
适配器,它是您的 FragmentStateAdapter
。
在此示例中,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中抽象出来。 创建一个“viewModel”:
data class PagerAdapterViewModel(
var ids : List<Int>
)
然后,在
PagerAdapter
中进行以下调整:
class PagerAdapter(
fm : Fragment,
private val viewModel : PagerAdapterViewModel
) : FragmentStateAdapter(fm){
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(){
...
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
...
}
...
}
viewPager.offscreenPageLimit = 3
并保存了当前项的状态。 - Mahmood Alibeta05
,看起来现在没问题了。 - extmkv