Flutter DragAndDropGridView初始预加载项过多崩溃,如何调整初始加载数量?
Flutter 拖拽GridView初始化预加载图片过多的解决方案
核心原因
你使用的拖拽GridView包默认基于官方SliverGrid实现,默认cacheExtent(预加载区域)设置较高,才会出现可视区仅8张但预加载到20张的情况,超出低内存设备的位图内存上限就会触发崩溃。
方法1:调整GridView预加载配置(最简便)
大部分拖拽GridView包都支持直接传递官方GridView的参数,调整两个参数即可直接降低预加载数量:
- 调整
cacheExtent为视口高度的1~1.2倍,这个参数控制视口外提前渲染的区域大小,调小后只会预加载视口外极少的内容 - 部分包支持直接设置
preloadCount参数,直接赋值为2即可,代表仅额外预加载视口外前后各2张内容
如果你的包没有暴露上述参数,可以直接fork包源码修改内部SliverGrid的对应配置。
示例代码:
DragAndDropGridView( // 仅预加载比视口高10%的区域,避免多余加载 cacheExtent: MediaQuery.of(context).size.height * 1.1, // 若包支持可直接设置预加载数量 preloadCount: 2, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, childAspectRatio: 1 ), itemBuilder: (context, index) => yourImageItem(index), // 其余原有配置 )
方法2:优化缩略图懒加载逻辑
配合你当前用的FutureBuilder,加一层可见性监听,只有当图片item进入可视区时才触发缩略图加载,从根源避免不可见项的资源占用:
- 监听item可见比例,仅当可见比例大于0时才执行缩略图获取的Future
- 获取缩略图时指定和你的item尺寸匹配的分辨率,不要加载过大的缩略图浪费内存
示例代码:
// 图片Item的State类内代码 bool _isThumbnailLoaded = false; Future<Uint8List>? _thumbnailFuture; @override Widget build(BuildContext context) { return VisibilityDetector( key: Key('grid_item_$index'), onVisibilityChanged: (visibilityInfo) { // 仅当item进入可视区且未加载过时才触发缩略图加载 if (visibilityInfo.visibleFraction > 0 && !_isThumbnailLoaded) { _thumbnailFuture = _getDeviceThumbnail(index, targetSize: 200); _isThumbnailLoaded = true; if (mounted) setState(() {}); } }, child: _isThumbnailLoaded ? FutureBuilder<Uint8List>( future: _thumbnailFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { return Image.memory(snapshot.data!, fit: BoxFit.cover); } return const ColoredBox(color: Color(0xFFEEEEEE)); }, ) : const ColoredBox(color: Color(0xFFEEEEEE)), ); }
方法3:截断初始化数据源(兜底方案)
如果包的预加载逻辑不可修改,可以直接控制传入的数据源长度:
- 初始化时仅传入前10条数据(可视区8张+2张冗余)
- 监听GridView滚动事件,当滚动到接近列表底部时,再分批追加剩余的图片数据到数据源中,完全控制加载数量
内容的提问来源于stack exchange,提问作者Dataman 5
相关产品推荐
相关产品推荐

