在Android中,是否有一种使用Paging Library 3.0实现基于游标的分页的方法?

3
我正在使用一个使用基于光标的分页来显示一些结果的REST API。我想知道是否可以使用Paging Library 3.0进行分页。我已经查看了一些媒体和文档,但似乎找不到实现它的方法。如果你们中有任何解决方案,请告诉我,我会非常高兴听到它!API响应分页的格式如下:
"paging": {
    "previous": false,
    "next": "https://api.acelerala.com/v1/orders/?store_id=4&after=xyz",
    "cursors": {
        "before": false,
        "after": "xyz"
    }
}
2个回答

2

感谢 @Đặng Anh Hào 的帮助,我终于找到了正确的方法。由于我的光标是字符串而不是整数,因此 Paging Source 加载函数如下:

override suspend fun load(params: LoadParams<String>): LoadResult<String, Order> {
    return try{
        val response = service.getOrders(query,params.key?:"",10)
        val nextKey = if(response.paging?.cursors?.after=="false") null else response.paging?.cursors?.after
        val prevKey = if(response.paging?.cursors?.before=="false") null else response.paging?.cursors?.before
        LoadResult.Page(response.data?.toOrderList()?:emptyList(),prevKey,nextKey)
    }catch (exception: IOException) {
        LoadResult.Error(exception)
    } catch (exception: retrofit2.HttpException) {
        LoadResult.Error(exception)
    }
}

而onrefreshkey看起来像这样:

override fun getRefreshKey(state: PagingState<String, Order>): String? {
    return state.anchorPosition?.let {
        state.closestItemToPosition(it)?.orderId
    }
}

仓储方法看起来像这样:

fun getOrdersPaginated(storeId: String): Flow<PagingData<Order>> {
    return Pager(
        config = PagingConfig(enablePlaceholders = false,pageSize = 10),
        pagingSourceFactory = {PagingSource(apiService,storeId)}
    ).flow

}

这是英语文本,翻译为:"

而且视图模型方法是这样的:

"。
private val _pagedOrders = MutableLiveData<PagingData<Order>>()
val orders get() = _pagedOrders

private var currentQueryValue: String? = null
private var currentSearchResult: Flow<PagingData<Order>>? = null

fun getOrdersPaginated(storeId: String) {
    viewModelScope.launch {
        currentQueryValue = storeId
        val newResult: Flow<PagingData<Order>> = repository.getOrdersPaginated(storeId)
            .cachedIn(viewModelScope)
        currentSearchResult = newResult
        currentSearchResult!!.collect {
            _pagedOrders.value = it
        }
    }
}

这段文字的英译中文如下:

该活动以以下方式调用分页:

private var searchJob: Job? = null

private fun getOrders() {
    viewModel.getOrdersPaginated(storeId)
}

private fun listenForChanges() {
    viewModel.orders.observe(this, {
        searchJob?.cancel()
        searchJob = lifecycleScope.launch {
            ordersAdapter.submitData(it)
        }
    })
}

最后,适配器与ListAdapter相同,唯一的不同之处在于它现在扩展了PagingDataAdapter<Order,OrderAdapter.ViewHolder>(OrdersDiffer)

如需更详细的教程,请查看此代码实验室


1
在Kotlin中,这里有一个例子。
在Activity或其他地方:
viewModel.triggerGetMoreData("data").collectLatest {
                mAdapter.submitData(it)
            }

在viewModel中:
fun triggerGetMoreData(data: String): Flow<PagingData<SampleData>> {
    val request = ExampleRequest(data)
    return exampleRepository.getMoreData(request).cachedIn(viewModelScope)
}

在代码库中:
fun getMoreData(request: ExampleRequest): Flow<PagingData<ExampleData>> {
    return Pager(
        config = PagingConfig(
            pageSize = 30,
            enablePlaceholders = false
        ),
        pagingSourceFactory = { ExamplePagingSource(service, request) }
    ).flow
}

并且

class ExamplePagingSource (
private val service: ExampleService,
private val request: ExampleRequest): PagingSource<Int, ExampleData>() {

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, ExampleData> {
    return try {
        val pageIndex = params.key ?: 0
        val request = request.copy(index = (request.pageNum.toInt() * pageIndex).toString())
        when (val result = service.getMoreData(request)) { // call api
            is NetworkResponse.Success -> {
                val listData = result.body.items?.toData()?: listOf()
                LoadResult.Page(
                    data = listData,
                    prevKey = if (pageIndex == 0) null else pageIndex - 1,
                    nextKey = if (listData.isEmpty()) null else pageIndex + 1
                )
            }
            else -> LoadResult.Error(result.toError())
        }
    } catch (e: Exception) {
        e.printStackTrace()
        LoadResult.Error(e)
    }
}

}


这种方法适用于基于游标的分页吗?API给我返回一个包含前后URL的分页对象,用于调用下一页或上一页。它也能与此一起工作吗? - undefined
请给我一个API的示例。 - undefined
检查 ExamplePagingSource 类:在接收到数据后,您需要修改请求以调用下一个 API。并根据您的上下文更改条件检查 prevKey 和 nextKey 的适当性。 - undefined
我已经更新了问题,并附上了包含分页信息的API响应,也许这能更清楚地说明我想要实现的目标。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接