Flutter使用flutter_cache_manager缓存图片遇空文件异常的解决办法
解决flutter_cache_manager缓存图片时的空文件/缺失异常问题
1. 捕获异常并触发重试下载
直接在调用getSingleFile(原getImageFile)时用try-catch包裹,同时主动检查文件有效性,一旦发现空文件或异常,先清理无效缓存再重新请求:
Future<File> getValidCachedImage(String url, {Map<String, String>? headers}) async { try { final file = await DefaultCacheManager().getSingleFile(url, headers: headers); // 主动校验文件大小,避免空文件 if (file.lengthSync() == 0) throw Exception("Empty cache file"); return file; } catch (_) { // 删除无效缓存条目 await DefaultCacheManager().removeFile(url); // 重新从网络拉取并缓存 return await DefaultCacheManager().getSingleFile(url, headers: headers); } }
2. 自定义CacheManager全局处理
通过继承BaseCacheManager实现自定义缓存管理器,把校验和重试逻辑封装进去,全局复用更方便:
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; class AppCacheManager extends BaseCacheManager { static const _cacheKey = "app_image_cache"; static AppCacheManager? _instance; factory AppCacheManager() { _instance ??= AppCacheManager._(); return _instance!; } AppCacheManager._() : super(_cacheKey); @override Future<String> getFilePath() async { // 用应用文档目录存储缓存,避免被系统自动清理 final directory = await getApplicationDocumentsDirectory(); return p.join(directory.path, _cacheKey); } @override Future<File> getSingleFile(String url, {Map<String, String>? headers}) async { try { final file = await super.getSingleFile(url, headers: headers); if (file.lengthSync() == 0) throw Exception("Empty cache file"); return file; } catch (_) { await removeFile(url); return super.getSingleFile(url, headers: headers); } } // 自定义缓存大小和有效期 @override int get maxCacheSize => 100 * 1024 * 1024; // 100MB @override Duration get maxCacheAge => Duration(days: 7); }
之后全局使用AppCacheManager()替代默认的DefaultCacheManager()即可。
3. 图片加载组件层面的容错
如果使用CachedNetworkImage或原生Image组件,配合错误处理逻辑,确保用户体验不受影响:
用CachedNetworkImage时:
CachedNetworkImage( imageUrl: "your_image_url", placeholder: (context, url) => CircularProgressIndicator(), errorWidget: (context, url, error) { // 加载失败时显示占位图,后台自动重试 AppCacheManager().getSingleFile(url); return Icon(Icons.image_not_supported, size: 48); }, )
用FutureBuilder配合FileImage时:
FutureBuilder<File>( future: AppCacheManager().getSingleFile("your_image_url"), builder: (context, snapshot) { if (snapshot.hasData && snapshot.data!.lengthSync() > 0) { return Image.file(snapshot.data!); } else if (snapshot.hasError) { return Icon(Icons.error); } return CircularProgressIndicator(); }, )
4. 避免缓存被系统清理
默认缓存目录属于系统可自动清理的范围,当设备存储空间不足时,系统可能会删除缓存文件。换成getApplicationDocumentsDirectory(如自定义CacheManager中所示)存储缓存,该目录下的文件不会被系统自动清理,能减少文件莫名消失的概率。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

