Flutter应用使用ListView.builder加载大量图片时崩溃求助
问题描述
使用ListView.builder展示604张单张大小165KB(总96MB)的图片时,应用启动直接崩溃;仅展示200张时,可运行滚动但一段时间后仍崩溃。已尝试ResizeImage、addAutomaticKeepAlives和shrinkWrap选项,均未解决问题。
代码示例:
main() { runApp( const Test(), ); } class Test extends StatelessWidget { const Test({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: SafeArea( child: ListView.builder( itemCount: 200, itemBuilder: (context, index) { String pageNum = ""; if ((index + 1) < 10) { pageNum = "00${index + 1}"; } else if ((index + 1) < 100 && (index + 1) > 9) { pageNum = "0${index + 1}"; } else { pageNum = "${index + 1}"; } return Image( image: AssetImage('images/mushaf_photos_2/page$pageNum.png'), fit: BoxFit.fill, ); }, ), ), ), ); } }
解决方案
1. 用缓存库管理本地图片加载
借助cached_network_image处理本地Asset图片,它会自动管理图片的缓存与内存释放,避免一次性加载过多资源:
- 先添加依赖:
flutter pub add cached_network_image - 修改加载代码:
return CachedNetworkImage( imageUrl: 'asset:///images/mushaf_photos_2/page$pageNum.png', fit: BoxFit.fill, );
2. 精准压缩图片解码尺寸
单独使用ResizeImage可能无效,需结合屏幕尺寸明确指定压缩后的宽高,确保只加载适合当前屏幕的图片尺寸:
return Image( image: ResizeImage( AssetImage('images/mushaf_photos_2/page$pageNum.png'), width: MediaQuery.of(context).size.width.toInt(), height: MediaQuery.of(context).size.height.toInt(), ), fit: BoxFit.fill, );
3. 给ListView指定固定项高度
在ListView.builder中设置itemExtent,帮助Flutter更高效地回收不可见项的内存:
ListView.builder( itemExtent: MediaQuery.of(context).size.height, // 与屏幕高度一致 itemCount: 604, // 其余逻辑不变 )
4. 改用PageView(适合翻页场景)
如果图片是按页浏览的场景,PageView默认只保留当前、前、后三页的图片,内存占用远低于ListView:
PageView.builder( itemCount: 604, itemBuilder: (context, index) { // 图片加载逻辑同上 }, )
5. 限制全局图片缓存大小
在应用启动时设置ImageCache的最大缓存容量,防止内存溢出:
main() { PaintingBinding.instance.imageCache.maximumSizeBytes = 50 * 1024 * 1024; // 限制为50MB runApp(const Test()); }
内容的提问来源于stack exchange,提问作者Youcef DOUKHI
相关产品推荐
相关产品推荐

