You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose搭配Paging3实现分页时Retrofit无限调用如何解决?

问题成因
  • 接口返回参数不匹配
    你计算分页边界和下一页页码完全依赖TMDB接口返回的page字段,如果请求的page参数和接口实际返回的page值不一致(比如参数传递错误,请求page=3但接口始终返回page=2),会导致你给当前页所有影片设置的nextKey始终为3,后续APPEND加载时会反复请求同一页,进入死循环。
  • 数据库表主键/插入逻辑错误
    1. RemoteKey表未给movieId设置唯一约束,同一个影片id会插入多条RemoteKey记录,查询时拿到旧的nextKey,导致重复请求
    2. Movie表主键配置错误,或者插入影片数据时使用普通insert而非upsert(冲突替换),重复数据插入失败但RemoteKey已写入,导致列表最后一条数据对应的nextKey不会更新,反复触发同页请求
  • 本地查询排序规则与接口返回不匹配
    如果movieDao().pagedTopRated()的查询排序逻辑和TMDB接口返回的排序逻辑不一致,新插入的分页数据会出现在列表头部而非尾部,你取到的列表最后一条数据还是上一页的记录,对应的nextKey还是当前请求的页码,触发重复请求。
排查步骤
  1. 在RemoteMediator的load方法中添加日志,打印每次请求的page值、接口返回的page、totalPages值,确认请求页码和返回页码是否一致,nextKey是否正常递增。
  2. 检查数据库表结构:确认RemoteKey表的movieId是唯一主键,Movie表的主键为影片id,插入数据的方法支持冲突时替换旧数据。
  3. 检查pagedTopRated方法的查询语句,确认排序规则和TMDB接口返回的排序规则完全一致。
修复方案
  1. 校验TMDB接口请求参数,确保page参数正确传递,TMDB分页接口的page参数从1开始,和你代码中计算的page值匹配。
  2. 调整数据库操作逻辑:
  • 给RemoteKey表的movieId字段添加唯一约束
  • 将movieDao.insertMovies和movieKeyDao.insertAll改为upsert逻辑,发生主键冲突时直接替换旧记录,示例代码:
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMovies(movies: List<Movie>)

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(keys: List<MovieKey>)
  1. 对齐本地查询和接口返回的排序规则,比如TMDB top rated接口按评分倒序、id升序排列,你的查询语句也要对应添加排序规则:
@Query("SELECT * FROM movie ORDER BY rating DESC, id ASC")
fun pagedTopRated(): PagingSource<Int, Movie>
  1. 添加兜底判断逻辑,拿到请求的page值后,如果page大于接口返回的totalPages,直接返回分页结束:
val response: MovieResponse = networkService.getTopRatedMovies(page)
// 新增兜底判断
if (page > response.totalPages) {
    return MediatorResult.Success(endOfPaginationReached = true)
}

内容的提问来源于stack exchange,提问作者Trixy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:06:01