android - ViewPager2 PagedList DiffUtil FragmentStateAdapter 中的片段重新创建时数据未刷新
问题描述
我试图在片段内的 ViewPager 选项卡中显示两组产品列表。我也在使用分页库。能够加载数据并且分页也可以正常工作。如果我在同一个片段中,我还能够使分页列表数据无效并重新加载。
从这个选项卡布局移动到另一个片段并返回到这个片段。我能够在两个选项卡中看到旧数据。但是重新加载/分页没有发生。使数据失效后,获取的新数据不显示。回收站视图包含旧数据。我从 API 获取数据并执行提交列表 - Diff Utils 也被调用。但是没有调用 ProductPagedListAdapter - 回收器视图方法。
我觉得重新创建片段适配器正在重新创建,但它并没有绑定到现有的回收器视图。我尝试了retainInstance,它不起作用。我在视图寻呼机中使用相同 ProductFragment 的两个不同实例。由于一些问题,我正在观察来自 Parent Fragment ProductTabFragment 的数据并将数据发送到 ViewPager 片段。
对此的任何帮助将不胜感激。
ViewPager 片段
class ProductTabFragment : Fragment() {
private lateinit var tabLayout: TabLayout
private lateinit var viewPager: ViewPager2
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val viewModel: ProductViewModel by viewModels(
ownerProducer = { activity as FragmentActivity },
factoryProducer = { viewModelFactory }
)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.product_tab_fragment, container, false)
tabLayout = view.findViewById(R.id.tabLayoutProduct)
viewPager = view.findViewById(R.id.viewPagerLayoutProduct)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewPager.apply {
adapter = ProductAdapter(childFragmentManager, viewLifecycleOwner.lifecycle, viewModel.getTabCount())
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
viewModel.selectedTab = position
}
})
TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = when (position) {
POSITION_TAB_RECOMMENDED -> TAB_TITLE_RECOMMENDED
POSITION_TAB_RECENT -> TAB_TITLE_RECENT
else -> TAB_TITLE_RECOMMENDED
}
}.attach()
}
viewModel.recommendedList.observe(viewLifecycleOwner, Observer {
sendDataToFragment(POSITION_TAB_RECOMMENDED, it)
})
viewModel.recentList.observe(viewLifecycleOwner, Observer {
sendDataToFragment(POSITION_TAB_RECENT, it)
})
}
override fun onAttach(context: Context) {
super.onAttach(context)
retainInstance = true
}
private fun sendDataToFragment(fragmentPosition: Int, productList: PagedList<Product>?) {
val mFragment: Fragment? =
(viewPager.adapter as? ProductTabPagerAdapter)?.tabFragments?.get(fragmentPosition)
mFragment?.let { (it as? ProductFragment)?.setUpListData(productList) }
}
companion object {
const val POSITION_TAB_RECOMMENDED = 0
const val POSITION_TAB_RECENT = 1
private const val TAB_TITLE_RECOMMENDED = "RECOMMENDED"
private const val TAB_TITLE_RECENT = "RECENT"
@JvmStatic
fun newInstance() = ProductTabFragment()
}
}
寻呼机适配器
class ProductTabPagerAdapter(fragmentManager: FragmentManager,
lifecycle: Lifecycle, val tabCount :Int) :
FragmentStateAdapter(fragmentManager,lifecycle) {
internal var tabFragments = listOf<Fragment>(ProductFragment.newInstance(ProductTabFragment.POSITION_TAB_RECOMMENDED),ProductFragment.newInstance(ProductTabFragment.POSITION_TAB_RECENT))
override fun getItemCount(): Int {
return tabCount
}
override fun createFragment(position: Int): Fragment {
return tabFragments[position]
}
}
**Same Reusable fragments used in ViewPager**
class ProductFragment : Fragment() {
private var productAdapter = ProductPagedListAdapter()
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
private val viewModel: ProductViewModel by viewModels(
ownerProducer = { activity as FragmentActivity },
factoryProducer = { viewModelFactory }
)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.productƒ_fragment, container, false)?.apply {
initialProgressBar = findViewById(R.id.initialLoadProgressBar)
loadMoreProgressBar = findViewById(R.id.loadMoreProgressBar)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById<RecyclerView>(R.id.productList)?.apply {
context?.also { ctx ->
layoutManager = LinearLayoutManager(ctx)
}
adapter = productAdapter
}
}
fun setUpListData(data: PagedList<Product>?) {
productAdapter.submitList(data)
}
override fun onAttach(context: Context) {
super.onAttach(context)
retainInstance = true
}
}
分页列表适配器
class ProductPagedListAdapter() : PagedListAdapter<Product, ProductItemHolder>(diffUtilCallBack) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductItemHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.product_item, parent, false)
return ProductItemHolder(view)
}
override fun onBindViewHolder(holder: ProductItemHolder, position: Int) {
getItem(position)?.let { holder.bind(it) }
}
companion object {
var diffUtilCallBack = object : DiffUtil.ItemCallback<Product>() {
override fun areItemsTheSame(
oldItem: Product,
newItem: Product
) = oldItem.id == newItem.id
override fun areContentsTheSame(
oldItem: Product,
newItem: Product
)= oldItem == newItem
}
}
}
查看模型
class ProductViewModel()) : ViewModel() {
var recommendedList : LiveData<PagedList<Product>> = MutableLiveData<PagedList<Product>>()
var recentList : LiveData<PagedList<Product>> = MutableLiveData<PagedList<Product>>()
init {
fetchRecentProducts()
fetchRecommended()
}
fun fetchRecommended() {
val pagedListConfig = PagedList.Config.Builder()
.setPageSize(ProductDataSource.PAGE_LIMIT)
.setEnablePlaceholders(false).build()
val dataSourceFactory = object : DataSource.Factory<Int, Product>() {
override fun create(): DataSource<Int, Product> {
return ProductDataSource(
type = "recommended",
)
}
}
recommendedList = LivePagedListBuilder<Int, Product>(
dataSourceFactory,
pagedListConfig
).build()
}
fun fetchRecent() {
val pagedListConfig = PagedList.Config.Builder()
.setPageSize(ProductDataSource.PAGE_LIMIT)
.setEnablePlaceholders(false).build()
val dataSourceFactory = object : DataSource.Factory<Int, Product>() {
override fun create(): DataSource<Int, Product> {
return ProductDataSource(
type = "recent",
)
}
}
recentList = LivePagedListBuilder<Int, Product>(
dataSourceFactory,
pagedListConfig
).build()
}
fun resetPaginationData() {
recommendedList.value?.dataSource?.invalidate()
recentList.value?.dataSource?.invalidate()
}
}
分页列表的数据源
class ProductDataSource(
private val type: String) : PageKeyedDataSource<Int, Product>() {
override fun loadInitial(
params: LoadInitialParams<Int>,
callback: LoadInitialCallback<Int, Product>
) {
compositeDisposable.add(
productRepo.getProductList(
tyoe
).subscribe(
{ productList ->
callback.onResult(
productList, null, PAGE_LIMIT
)
}
)
}
}
解决方案
推荐阅读
- javascript - 如何让图像在 HTML 中显示一定次数的 Val
- flutter - 带有 WebView 的溢出容器
- regex - 使用多个括号分组时 sed 没有输出
- laravel - 我可以让用户与每个角色相关联吗 - laravel
- java - Intellij 构建工件 - 可运行的 jar UTF-8
- apache-beam - Apache Bean Spark Runner 在流模式下不起作用 - java.lang.IllegalAccessException
- nuxt.js - 在模块中使用 Nuxt 中的运行时环境变量
- javascript - 如何根据javascript循环中的交互次数创建级联属性?
- javascript - 如何将 Postgres bytea 转换为 base64 字符串
- java - 异常(选中和未选中)