GridLayoutManager列数增至5时Android图库应用出现严重卡顿
解决GridLayoutManager列数设为5时RecyclerView滑动卡顿问题
嘿,这个问题我太熟悉了——当列数调到5之后,屏幕上可见的ImageView数量一下子增加了不少(比4列多了25%左右),快速滑动时RecyclerView要快速完成视图绑定、布局、绘制,再加上图片加载的并发请求飙升,直接把主线程压垮,就出现了你看到的Systrace红块。咱们一步步来针对性优化:
1. 先从图片加载下手(图库应用卡顿的重灾区)
- 加载适配尺寸的缩略图,别让主线程做缩放:列数为5时,每个ImageView的宽度是「屏幕宽度/5」,提前算好这个精确尺寸(别忘了减去item之间的间距),然后让你的图片加载库(Glide/Coil/Picasso)直接加载对应尺寸的缩略图。比如用Glide的话,就加个
override(targetWidth, targetHeight),彻底避免在主线程做图片缩放的耗时操作。 - 调整滑动时的加载优先级:给RecyclerView加个滚动监听,滑动过程中把图片加载的优先级设为低(比如Glide的
priority(Priority.LOW)),滑动停止后再恢复正常优先级。这样滑动时系统会优先处理UI渲染,而非图片加载。 - 优化缓存策略:确保内存缓存和磁盘缓存配置合理,比如给Glide设置合适的内存缓存大小(别太小也别太大导致OOM),重复显示的图片直接从缓存取,不用重新下载解码。
2. 给RecyclerView“减负”
- 开启固定尺寸模式:如果你的RecyclerView整体尺寸不会变化(比如高度是match_parent),一定要加上
recyclerView.setHasFixedSize(true),这样RecyclerView不用每次滑动都重新计算整体布局,能省不少主线程资源。 - 加大视图缓存:用
recyclerView.setItemViewCacheSize()设置一个比屏幕可见item数多2-3的缓存值,让RecyclerView提前预加载下一批视图,滑动时不用临时创建ViewHolder,减少突发的布局压力。 - 固定ImageView的尺寸:别让ImageView用
wrap_content来自适应高度,提前通过代码或者ConstraintLayout的layout_constraintDimensionRatio把ImageView设为固定比例(比如正方形),避免RecyclerView在布局时反复测量每个item的尺寸。
3. 减少视图绘制的开销
- 检查过度绘制:用Android Studio Profiler里的Overdraw工具看看,是不是ImageView有不必要的背景、阴影,或者父布局的背景和ImageView重叠了。把多余的背景去掉,或者用
android:clipToPadding="true"限制绘制区域,能大幅减少绘制耗时。 - 别在
onBindViewHolder里做耗时操作:所有数据处理、图片解码这类事都扔到后台线程,onBindViewHolder里只做最简单的UI赋值操作——比如给ImageView设置加载请求,给TextView设文字,别在这儿搞任何计算逻辑。
4. 用Systrace精准定位
你已经看到了Systrace的红块,接下来可以放大看红块对应的具体操作:是performTraversals(布局/绘制)耗时,还是图片加载的回调占了主线程?
- 如果是布局耗时:重点优化item视图的测量逻辑,确保每个item的尺寸能快速确定。
- 如果是绘制耗时:回到上面的过度绘制优化,或者检查有没有自定义View的
onDraw做了复杂操作。 - 如果是图片加载:调整加载策略,比如减少并发加载的数量,或者用更高效的解码方式。
按这个顺序排查优化,基本能解决5列时的滑动卡顿问题。
内容的提问来源于stack exchange,提问作者BigDX
相关产品推荐
相关产品推荐

