Paging 3调用adapter.refresh()时如何避免列表自动滚动到顶部?
Paging 3 刷新不滚动到顶部解决方案
核心问题原因
你当前PagingSource中的getRefreshKey方法直接返回null,是触发刷新后列表回滚顶部的直接原因。Paging 3执行刷新操作时,会通过该方法获取当前列表可视区域对应位置的分页游标,以此为起点加载刷新后的数据,即可保持原有浏览位置。当返回值为null时,Paging会默认从初始页(第一页)开始加载,列表自然会滚动到顶部。
修复步骤
1. 重写getRefreshKey逻辑
修改你的SearchProductDataSource中的getRefreshKey方法,返回当前浏览位置对应的分页key:
override fun getRefreshKey(state: PagingState<String, Product>): String? { // 获取当前列表可视区域的锚点位置,无锚点直接返回null val anchorPosition = state.anchorPosition ?: return null // 获取锚点位置对应的分页信息 val targetPage = state.closestPageToPosition(anchorPosition) ?: return null // 优先取当前页的下一页游标,无则取上一页游标 return targetPage.nextKey ?: targetPage.prevKey }
修改完成后调用adapter.refresh()就会从你当前浏览的分页位置开始加载,不会跳转到顶部。
2. 局部刷新优化(可选,适配心愿单更新场景)
如果你只是修改单条商品的心愿单状态,不需要调用全量刷新方法adapter.refresh(),直接局部更新对应条目即可,性能更好且完全不会触发列表滚动:
// 假设你已知要更新的商品在列表中的索引位置position adapter.snapshot()[position]?.let { oldProduct -> // 生成修改心愿单状态后的新商品对象 val updatedProduct = oldProduct.copy(isWished = !oldProduct.isWished) // 通知适配器局部更新该条目 adapter.notifyItemChanged(position, updatedProduct) }
注意事项
- 确认你没有在适配器的
addLoadStateListener监听刷新状态的逻辑中,主动调用了RecyclerView.scrollToPosition(0)这类滚动到顶部的代码,否则上述修改会被手动滚动逻辑覆盖。
内容的提问来源于stack exchange,提问作者a-rohim
相关产品推荐
相关产品推荐

