使用Jetpack Paging3时列表首次滚动卡顿问题求助
Paging3集成首次滚动卡顿问题排查
问题背景
我创建了一个集成Jetpack Paging3分页库的简单示例项目,项目地址:Paging3-Sample
目前页面触发第一次滚动时会出现明显卡顿,始终无法定位问题原因,各层实现代码如下:
PagingSource层实现
private const val STARTING_PAGE_INDEX = 1 class ShowPagingSource( private val service: ShowService ) : PagingSource<Int, Show>() { override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Show> { val page = params.key ?: STARTING_PAGE_INDEX return try { val response = service.fetchShowList(page) LoadResult.Page( data = response, prevKey = if (page == STARTING_PAGE_INDEX) null else page - 1, nextKey = if (response.isEmpty()) null else page + 1 ) } catch (exception: IOException) { LoadResult.Error(exception) } catch (exception: HttpException) { LoadResult.Error(exception) } } }
Repository层实现
@Singleton class ShowRepositoryImpl @Inject constructor(private val service: ShowService) : ShowRepository { override val fetchResultStream: Flow<PagingData<Show>> = Pager( config = PagingConfig(pageSize = NETWORK_PAGE_SIZE), pagingSourceFactory = { ShowPagingSource(service) } ).flow companion object { const val NETWORK_PAGE_SIZE = 245 } }
ViewModel层实现
@HiltViewModel class ShowViewModel @Inject constructor( repository: ShowRepository ) : ViewModel() { val pagingDataFlow: Flow<PagingData<Show>> = repository.fetchResultStream.cachedIn(viewModelScope) }
Activity层数据提交逻辑
lifecycleScope.launch { viewModel.pagingDataFlow.collectLatest(showAdapter::submitData) }
核心疑问:现有实现是否存在遗漏配置?首次滚动卡顿的根本原因是什么?
问题根因与修复方案
首次滚动卡顿完全是配置不合理导致的,不存在遗漏的核心逻辑,具体问题点和修复方式如下:
- pageSize配置严重偏大:当前设置单页加载245条数据,远高于移动端列表单页加载的合理区间(常规取值20-50条)。Paging3默认的预加载触发距离与pageSize相等,且首次加载大小默认是pageSize的3倍,该配置下首次会拉取700+条数据,DiffUtil在主线程对比数百条数据差异时会直接阻塞UI线程,引发明显卡顿。
- 占位符配置与Adapter实现不匹配:
PagingConfig默认开启占位符(enablePlaceholders = true),如果Adapter没有实现对应占位符ViewHolder逻辑,Paging3计算列表总高度、滚动偏移时会出现偏差,首次滚动时会瞬间插入大量条目触发全列表重绘,进一步加剧卡顿。不需要占位符时直接显式关闭该配置即可。 - 缺少RecyclerView基础优化:检查RecyclerView是否调用了
setHasFixedSize(true),列表项布局是否使用固定高度避免滚动时重复触发measure/layout;同时确认Show数据类正确实现了equals和hashCode方法,否则DiffUtil会做全量数据对比,额外增加大量主线程耗时。
修复参考配置
修改Repository层的Pager配置即可解决绝大多数卡顿场景:
Pager( config = PagingConfig( pageSize = 30, // 单页加载条数调整到合理区间 prefetchDistance = 10, // 距离底部10条时提前触发预加载 enablePlaceholders = false, // 未适配占位符则显式关闭 initialLoadSize = 30 // 首次加载大小与pageSize对齐,避免首次拉取数据过多 ), pagingSourceFactory = { ShowPagingSource(service) } ).flow
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

