问题描述
请帮助我。
该应用仅用于接收来自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
更改为loadState
:https://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
字段更新您的标题。
它确实不是很优雅,因为您在所有项目中都发送它,但它比其他建议的解决方案更好。