|
1 | | -import 'package:file/local.dart'; |
| 1 | +import 'dart:io'; |
| 2 | +import 'dart:developer'; |
| 3 | +import 'package:rxdart/rxdart.dart'; |
2 | 4 | import 'package:path/path.dart' as p; |
3 | 5 | import 'package:path_provider/path_provider.dart'; |
4 | 6 | import 'package:flutter_cache_manager/flutter_cache_manager.dart'; |
5 | 7 |
|
6 | 8 | class CustomCacheManager { |
7 | | - static const key = 'customCacheKey'; |
| 9 | + static const String _key = 'customCacheKey'; |
8 | 10 |
|
9 | | - static CacheManager instance = CacheManager( |
| 11 | + static final CacheManager instance = CacheManager( |
10 | 12 | Config( |
11 | | - key, |
| 13 | + _key, |
12 | 14 | stalePeriod: const Duration(days: 1), |
13 | | - maxNrOfCacheObjects: 20, |
14 | | - repo: JsonCacheInfoRepository(databaseName: key), |
15 | | - fileSystem: IOFileSystem(key), |
| 15 | + maxNrOfCacheObjects: 2000, |
| 16 | + repo: JsonCacheInfoRepository(databaseName: _key), |
| 17 | + fileSystem: IOFileSystem(_key), |
16 | 18 | fileService: HttpFileService(), |
17 | 19 | ), |
18 | 20 | ); |
19 | 21 |
|
20 | | - static Future<double> cacheSize() async { |
21 | | - var baseDir = await getTemporaryDirectory(); |
22 | | - var path = p.join(baseDir.path, key); |
| 22 | + static final _sizeController = BehaviorSubject<double>.seeded(0.0); |
| 23 | + static Stream<double> get cacheSizeStream => _sizeController.stream; |
23 | 24 |
|
24 | | - var fs = const LocalFileSystem(); |
25 | | - var directory = fs.directory((path)); |
26 | | - return (await directory.stat()).size / 8 / 1000; |
| 25 | + static final _updateTrigger = PublishSubject<void>(); |
| 26 | + |
| 27 | + static void init() { |
| 28 | + _updateTrigger |
| 29 | + .throttleTime(const Duration(seconds: 2), trailing: true, leading: true) |
| 30 | + .asyncMap((_) => _calculateSize()) |
| 31 | + .listen((size) { |
| 32 | + _sizeController.add(size); |
| 33 | + log('缓存大小已更新: ${size.toStringAsFixed(2)} MB'); |
| 34 | + }); |
| 35 | + |
| 36 | + // 初始统计一次 |
| 37 | + notifyUpdate(); |
| 38 | + } |
| 39 | + |
| 40 | + static void notifyUpdate() => _updateTrigger.add(null); |
| 41 | + |
| 42 | + static Future<double> _calculateSize() async { |
| 43 | + final baseDir = await getTemporaryDirectory(); |
| 44 | + int totalBytes = 0; |
| 45 | + |
| 46 | + final fileDir = Directory(p.join(baseDir.path, _key)); |
| 47 | + if (await fileDir.exists()) { |
| 48 | + await for (var file in fileDir.list(recursive: true)) { |
| 49 | + if (file is File) totalBytes += await file.length(); |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + final dbFile = File(p.join(baseDir.path, '$_key.json')); |
| 54 | + if (await dbFile.exists()) { |
| 55 | + totalBytes += await dbFile.length(); |
| 56 | + } |
| 57 | + |
| 58 | + // 转换为 MB (1024 * 1024) |
| 59 | + return totalBytes / (1024 * 1024); |
27 | 60 | } |
28 | 61 |
|
| 62 | + /// 彻底清理缓存:清理数据库 + 物理删除文件夹 |
29 | 63 | static Future<void> clearCache() async { |
30 | | - var baseDir = await getTemporaryDirectory(); |
31 | | - var path = p.join(baseDir.path, key); |
| 64 | + try { |
| 65 | + await instance.emptyCache(); |
| 66 | + |
| 67 | + // 2. 物理删除残留文件夹和 JSON 数据库文件 |
| 68 | + final baseDir = await getTemporaryDirectory(); |
| 69 | + final dirPath = p.join(baseDir.path, _key); |
| 70 | + final dbPath = p.join(baseDir.path, '$_key.json'); |
| 71 | + |
| 72 | + final dir = Directory(dirPath); |
| 73 | + if (await dir.exists()) await dir.delete(recursive: true); |
| 74 | + |
| 75 | + final db = File(dbPath); |
| 76 | + if (await db.exists()) await db.delete(); |
| 77 | + |
| 78 | + log('清除缓存成功'); |
| 79 | + |
| 80 | + // 立即重置流状态 |
| 81 | + _sizeController.add(0.0); |
| 82 | + } catch (e) { |
| 83 | + log('清理缓存失败: $e'); |
| 84 | + } |
| 85 | + } |
32 | 86 |
|
33 | | - var fs = const LocalFileSystem(); |
34 | | - var directory = fs.directory((path)); |
35 | | - await directory.delete(recursive: true); |
| 87 | + /// 销毁资源 |
| 88 | + static void dispose() { |
| 89 | + _sizeController.close(); |
| 90 | + _updateTrigger.close(); |
36 | 91 | } |
37 | 92 | } |
0 commit comments