Flutter列表滚动卡顿怎么优化?

打工人子轩 阅读 11

我用ListView.builder加载了上百条带图片的数据,滑动时明显掉帧,试过加const widget和cacheExtent也不太行。是不是图片没处理好?

这是我在Item里用的样式:

.item-container {
  width: 100%;
  padding: 12px;
  border-bottom: 1px solid #eee;
}
.item-image {
  width: 60px;
  height: 60px;
  object-fit: cover;
}
我来解答 赞 0 收藏
二维码
手机扫码查看
1 条解答
Mc.柯佳
Mc.柯佳 Lv1
图片这块没处理好是大概率原因。给你几个实打实的优化方向:

第一,强烈建议用cached_network_image代替Image.network。它自带缓存和占位图,不会每次滑动都触发网络请求。代码大概是这样:

CachedNetworkImage(
imageUrl: item.imageUrl,
width: 60,
height: 60,
fit: BoxFit.cover,
placeholder: (context, url) => Container(
width: 60,
height: 60,
color: Colors.grey[200], // 占位背景
),
errorWidget: (context, url, error) => Icon(Icons.error),
)


第二,记得给图片指定cacheWidth和cacheHeight。Flutter默认会按原图尺寸缓存,很占内存。60px的展示区域完全没必要缓存原图:

CachedNetworkImage(
imageUrl: item.imageUrl,
cacheWidth: 120, // 2倍像素密度,清晰度更好
cacheHeight: 120,
// ...
)


第三,检查你的Item Widget有没有不必要的重绘。确保用const构造函数,build方法里不要创建新的Widget对象。如果Item里还有其他复杂组件,考虑用RepaintBoundary包一下:

RepaintBoundary(
child: ItemWidget(...),
)


第四,如果数据量确实很大,可以考虑用ListView的itemExtent属性指定固定高度,这样Flutter不用每次都去计算每个item的高度,能提升不少:

ListView.builder(
itemExtent: 84, // 60px图片 + 12px上下padding + 边框
itemBuilder: (context, index) => ItemWidget(...),
)


还有一个小提醒:如果你这列表是频繁更新的(比如实时聊天或者数据会变),记得用AutomaticKeepAliveClientMixin保持住状态,不然每次滚动出去再回来会重新加载。

基本上就是图片缓存没做好导致的,优先换cached_network_image + 限制缓存尺寸这两步,卡顿应该能明显改善。
点赞
2026-03-18 22:02