首页 > 解决方案 > 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
                    )
                }
        )
    }
}

标签: androidandroid-fragmentsandroid-viewpager2android-pagingfragmentstateadapter

解决方案


推荐阅读