【发布时间】:2021-10-05 01:28:31
【问题描述】:
我正在试用 Paging 3.0.1 版本。当我打印日志时,API 调用正在发生。但显示的数据是重复的。谁能告诉我哪里出错了?
页面数据源类
class MyPageDataSource(private val api: RetrofitInstance) :
PagingSource<Int, APIDataResponse>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, APIDataResponse> {
return try {
val nextPageNumber = params.key ?: FIRST_PAGE_NUMBER
val response = api.getData(nextPageNumber, PAGE_SIZE)
LoadResult.Page(
data = response.APIS!!,
prevKey = if (nextPageNumber > FIRST_PAGE_NUMBER) nextPageNumber - 1 else null,
nextKey = if (nextPageNumber * PAGE_SIZE < response.total!!) nextPageNumber + 1 else null
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, APIDataResponse>): Int? {
return state.anchorPosition
}
companion object {
const val FIRST_PAGE_NUMBER = 1
const val PAGE_SIZE = 20
}
}
适配器:
class MyListingAdapter() : PagingDataAdapter<APIDataResponse, MyListingAdapter.MyViewHolder>(MyComparator) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(
FragmentItemBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
)
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(item = getItem(position))
}
inner class MyViewHolder(binding: FragmentItemBinding) :
RecyclerView.ViewHolder(binding.root) {
private val title: TextView = binding.title
fun bind(item: APIDataResponse?) {
if(item != null) {
title.text = item.title
}
}
}
object MyComparator : DiffUtil.ItemCallback<APIDataResponse>() {
override fun areItemsTheSame(
oldItem: APIDataResponse,
newItem: APIDataResponse
): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(
oldItem: APIDataResponse,
newItem: APIDataResponse
): Boolean {
return oldItem == newItem
}
}
}
查看模型:
class PagingViewModel : ViewModel() {
fun getData() : Flow<PagingData<APIDataResponse>> {
return Pager(
PagingConfig(
pageSize = 20,
enablePlaceholders = false,
maxSize = 40,
initialLoadSize = 20,
prefetchDistance = 10
)
) {
MyPageDataSource(RetrofitInstance())
}.flow.cachedIn(viewModelScope)
}
}
在片段中设置回收站视图:
val myAdapter = MyListingAdapter(myActivity)
//Setup the recyclerview
binding.myList.apply {
layoutManager = when {
columnCount <= 1 -> LinearLayoutManager(context)
else -> GridLayoutManager(context, columnCount)
}
myAdapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY
val decoration =
DividerItemDecoration(myActivity, DividerItemDecoration.VERTICAL)
addItemDecoration(decoration)
setHasFixedSize(true)
adapter = myAdapter
}
lifecycleScope.launch {
viewModel.getData().distinctUntilChanged().collectLatest { pagedData ->
myAdapter.submitData(pagedData)
}
}
【问题讨论】:
-
嗨,您能解释一下您在 nextKey 中尝试做什么吗?因为那是用来检查我们是否需要加载更多页面,所以我在那里完成的实现是 nextKey = if (response.isEmpty()) null else position + 1,这与你的 api 的工作方式有关吗?
-
每页包含 20 个结果,即 PAGE_SIZE。 nextPageNumber * PAGE_SIZE 将返回加载的结果数。我的 API 返回了总字段。所以,我正在检查乘积与总数。
-
您的
APIDataResponse是“数据类”吗?在我看来,重复发生在DiffUtil.ItemCallback -
@A.David 是的,它是一个数据类
标签: android kotlin paging android-paging android-paging-3