分页库3.0:如何将项目总数传递给列表标题?

问题描述

请帮助我。
该应用仅用于接收来自https://trefle.io的植物列表并将其显示在RecyclerView中。
在这里使用Paging库3.0。
任务:我想添加一个标题,以显示植物的总数。
问题:我只是找不到一种方法将总项目的值传递给标题

    Data model:  
    data class PlantsResponSEObject(
    @Serializedname("data")
    val data: List<PlantModel>?,@Serializedname("Meta")
    val Meta: Meta?
) {
    data class Meta(
        @Serializedname("total")
        val total: Int? // 415648
    )
}
   data class PlantModel(
    @Serializedname("author")
    val author: String?,@Serializedname("genus_id")
    val genusId: Int?,@Serializedname("id")
    val id: Int?)

DataSource类:

class PlantsDataSource(
    private val plantsApi: PlantsAPI,private var filters: String? = null,private var isvegetable: Boolean? = false

) : RxPagingSource<Int,PlantView>() {

    override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int,PlantView>> {
        val nextPageNumber = params.key ?: 1
           return plantsApi.getPlants(  //API call for plants
               nextPageNumber,//different filters,does not matter
               filters,isvegetable)
               .subscribeOn(Schedulers.io())
               .map<LoadResult<Int,PlantView>> {
                   val total = it.Meta?.total ?: 0 // Here I have an access to the total count
 //of items,but where to pass it?
                    LoadResult.Page(
                       data = it.data!! //Here I can pass only plant items data
                           .map { PlantView.PlantItemView(it) },prevKey = null,nextKey = nextPageNumber.plus(1)
                   )
               }
               .onErrorReturn{
                   LoadResult.Error(it)
               }
    }

    override fun invalidate() {
        super.invalidate()
    }
}

LoadResult.Page只接受植物列表本身。而且DataSource之上的所有类(Repo,viewmodel,Activity)都无法访问响应对象。
问题:如何将项目总数传递给列表标题
我将不胜感激。

解决方法

一种方法是使用MutableLiveData,然后对其进行观察。例如

pagingDataSource.countPlants.observe(viewLifecycleOwner) { count ->
    //update your view with the count value
}

然后在您的回收站视图所在的地方。

parseFloat
,

Paging中的withHeader函数仅返回给定ConcatAdapter的{​​{1}},其中有一些代码可以根据适配器的LoadStateHeader进行监听和更新。

通过实现自己的LoadState,您应该能够执行非常相似的操作,除了监听ItemCountAdapter,而不是监听LoadState的更改。您需要构建一个流程/侦听器来决定何时发送更新,但是您只需将loadState更改映射到itemCount。

请参阅此处以获取adapter.itemCount代码,您基本上可以复制它们,并将LoadStateAdapter更改为loadStatehttps://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:paging/runtime/src/main/java/androidx/paging/LoadStateAdapter.kt?q=loadstateadapter

例如

itemCount

...

然后要实际创建abstract class ItemCountAdapter<VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>() { var itemCount: Int = 0 set(itemCount { ... } open fun displayItemCountAsItem(itemCount: Int): Boolean { return true } ,您需要类似于https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:paging/runtime/src/main/java/androidx/paging/PagingDataAdapter.kt;l=236?q=withLoadStateHeader&sq=

ConcatAdapter
,

首次尝试使用Paging时遇到了同样的难题,尽管它为分页目的进行了计数,但它没有提供获取计数的方法(即Paging库首先使用COUNT(*)在进行其余查询之前先查看是否有比规定PagingConfig值更多或更少的项目,它可以完美地返回找到的结果总数)。

目前实现此目的的唯一方法是并行运行两个查询:一个针对您的商品(如您所拥有的),另一个仅计算与上一个查询参数相同的查询参数找到的结果数量,但仅适用于COUNT(*)

没有必要以PagingDataSource<LivedData<Integer>>的形式返回后者,因为这样会不必要地增加很多样板。只需将其作为普通的LivedData<Integer>来返回即可,这样只要列表结果发生更改,它就会一直在更新自身,否则它会遇到列表大小更改的问题,并且如果您第一次加载该值,则该值不会更新返回纯Integer

设置完两个适配器后,然后使用RecyclerView将它们添加到ConcatAdapter适配器中,并按照您希望它们在屏幕上显示的相同顺序使用上述适配器的顺序。列表。

例如:如果您希望计数显示在列表的开头/顶部,请先设置ConcatAdapter,首先使用计数适配器,然后使用列表项适配器。

,

您可以将 PagingData 类型更改为 Pair<PlantView,Int>(或任何其他结构)以添加您需要的任何信息。 然后,您将能够通过执行类似于以下操作的页面发送总计:

LoadResult.Page(
   data = it.data.map { Pair(PlantView.PlantItemView(it),total) },prevKey = null,nextKey = nextPageNumber.plus(1)
)

并在您的 ModelView 中执行任何操作,例如再次将其映射到 PlantItemView,但使用 second 字段更新您的标题。

它确实不是很优雅,因为您在所有项目中都发送它,但它比其他建议的解决方案更好。