Jetpack Paging 3.0结合Airbnb/Epoxy仅加载第一页问题求助
核心错误
你的代码之所以只能加载第一页,根源是AllCharacterPagingSource里的上一页键(prevKey)计算逻辑完全写反了:
你当前的实现:
val prevKey = if (pageNumber == 1) null else pageNumber + 1
这段逻辑有两个致命问题:
- prevKey代表当前页的上一页页码,当前页为N时上一页必然是N-1,你写成了N+1,和下一页页码逻辑混淆
- 错误的键值会导致Paging库计算相邻页位置完全失效,根本无法触发下一页的加载请求
除此之外还有几个会导致分页失效的隐患,按下面步骤逐一修复即可。
修复方案
1. 重写PagingSource的load方法分页键逻辑,补全异常捕获
override suspend fun load( params: LoadParams<Int> ): LoadResult<Int, Character> { return try { val pageNumber = params.key ?: 1 // 修正:第一页无上一页返回null,其余页上一页为当前页号-1 val prevKey = if (pageNumber == 1) null else pageNumber - 1 val response = NetworkLayer.apiClient.getAllCharactersByPage(pageNumber) // 替换原来的异常判断:Retrofit先判断请求成功再取响应体 if (!response.isSuccessful) { return LoadResult.Error(IllegalStateException("请求失败,错误码:${response.code()}")) } val responseBody = response.body() ?: return LoadResult.Error(NullPointerException("响应体为空")) LoadResult.Page( data = responseBody.results.map { CharacterMapper.buildFrom(it) }, prevKey = prevKey, nextKey = getPageIndexFromNext(responseBody.info.next) ) } catch (e: Exception) { // 所有请求、解析异常都要包装成Error返回,避免分页流程崩溃 LoadResult.Error(e) } }
同时给页码解析方法加异常防护,避免格式异常导致崩溃:
private fun getPageIndexFromNext(next: String?): Int?{ return runCatching { next?.split("?page=")?.get(1)?.toInt() }.getOrNull() }
2. 核对PagingConfig配置
Rick and Morty API单页固定返回20条数据,确保你的常量配置符合要求:
Constants.PAGE_SIZE设置为20,和接口单页返回条数一致Constants.PREFETCH_SIZE建议设置为和PAGE_SIZE相同的值(20),预加载距离过小也会导致滚动时不触发下一页加载
PagingConfig( pageSize = 20, prefetchDistance = 20, enablePlaceholders = false )
3. 修正RecyclerView布局配置
检查XML布局中charactersEpoxyRecyclerView的layout_height属性,绝对不能设置为wrap_content,必须设为match_parent或固定高度。wrap_content会让RecyclerView一次性测量所有子项,完全破坏Paging基于滚动位置触发预加载的逻辑。
4. 修正Fragment代码顺序与笔误
你贴的代码里有笔误iewLifecycleOwner,同时要注意先给RecyclerView设置Epoxy控制器,再开始收集分页数据,避免数据提交时控制器未绑定:
// 先绑定控制器 binding.charactersEpoxyRecyclerView.setController(pagingEpoxyController) // 再收集数据 viewLifecycleOwner.lifecycleScope.launch { allCharactersViewModel.flow.collectLatest { pagingEpoxyController.submitData(it) } }
优化建议
你的EpoxyController实现里直接持有Context引用会有内存泄漏风险,不要把Activity/Fragment的Context传入EpoxyModel,需要Context时可以通过绑定的View获取,或者使用Application级别的Context。
内容的提问来源于stack exchange,提问作者Siege Elevate
相关产品推荐
相关产品推荐

