如何解决flutter_cache_manager删除文件时的PathNotFoundException?
解决方案:flutter_cache_manager删除缓存时触发PathNotFoundException
问题原因
这是**竞态条件(TOCTOU问题:检查时间与使用时间不一致)**导致的:
- 代码先检查文件是否存在,到执行删除操作的间隙,文件可能被其他线程、进程(比如应用内其他缓存操作)或系统(iOS/macOS的自动缓存清理)提前删除,因此执行删除时触发「文件不存在」异常。
具体解决办法
1. 捕获删除操作的异常
在调用缓存删除的代码处,直接捕获PathNotFoundException并忽略——因为此时文件已经不存在,无需额外处理:
import 'dart:io'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; // 示例:删除指定缓存键的文件 Future<void> removeCache(String key) async { final cacheManager = DefaultCacheManager(); try { await cacheManager.removeFile(key); } on PathNotFoundException catch (_) { // 文件已不存在,跳过处理 } }
2. 修改flutter_cache_manager源码逻辑(或自定义CacheStore)
如果不想在业务代码里重复捕获异常,可以修改CacheStore._removeCachedFile方法,移除「先检查存在再删除」的逻辑,直接尝试删除并捕获异常:
// 修改cache_store.dart中的_removeCachedFile方法 Future<void> _removeCachedFile(CacheObject cacheObject) async { try { final file = _fileSystem.file(cacheObject.path); // 直接尝试删除,不再提前检查exists await file.delete(); await _database.deleteData(cacheObject.id); } on PathNotFoundException catch (_) { // 文件已被删除,仅清理数据库记录 await _database.deleteData(cacheObject.id); } catch (e) { // 处理其他删除异常 print('Failed to remove cached file: $e'); } }
注:如果不想fork包,可以自定义
CacheStore继承自原类,重写该方法后传入自定义的CacheManager。
3. 兼容系统自动清理行为
iOS/macOS的Library/Caches目录属于系统可自动清理的缓存目录,当设备空间不足时系统会主动删除其中文件。如果需要避免这种情况,可以将缓存存储到非自动清理目录(比如Application Support),但需要注意:
- 手动管理缓存大小,避免占用过多空间
- 修改flutter_cache_manager的存储路径配置:
final customCacheManager = CacheManager( Config( 'customCacheKey', stalePeriod: const Duration(days: 7), // 指定自定义存储目录 repo: JsonCacheInfoRepository(databaseName: 'customCacheKey'), fileSystem: IOFileSystem( Directory('/path/to/non-clearing-directory'), ), ), );
内容的提问来源于stack exchange,提问作者Sowat Kheang
相关产品推荐
相关产品推荐

