api_cache.dart 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import 'package:flutter/foundation.dart';
  2. /// 简单内存缓存,用于基础资料分页接口。
  3. /// TTL 内相同 cacheKey 的请求直接返回缓存结果。
  4. class ApiCache {
  5. final int ttlSeconds;
  6. final String? _keyPrefix;
  7. final Map<String, _CacheEntry> _store = {};
  8. ApiCache({this.ttlSeconds = 120, String? keyPrefix}) : _keyPrefix = keyPrefix;
  9. String _fullKey(String key) =>
  10. _keyPrefix != null ? '${_keyPrefix}_$key' : key;
  11. /// 缓存命中返回已有数据;未命中调用 [fetcher] 并存入缓存。
  12. /// [skipCache] 为 true 时跳过缓存直接调用 [fetcher]。
  13. Future<List<T>> getOrFetch<T>(
  14. String key,
  15. Future<List<T>> Function() fetcher, {
  16. bool skipCache = false,
  17. }) async {
  18. final fullKey = _fullKey(key);
  19. if (!skipCache) {
  20. final entry = _store[fullKey];
  21. if (entry != null && !entry.isExpired) {
  22. if (kDebugMode) debugPrint('[ApiCache] HIT $fullKey');
  23. return entry.data as List<T>;
  24. }
  25. }
  26. if (kDebugMode) debugPrint('[ApiCache] MISS $fullKey');
  27. final data = await fetcher();
  28. _store[fullKey] = _CacheEntry(
  29. data,
  30. DateTime.now().add(Duration(seconds: ttlSeconds)),
  31. );
  32. return data;
  33. }
  34. /// 移除指定 key 的缓存条目。
  35. void invalidate(String key) => _store.remove(_fullKey(key));
  36. /// 清除所有缓存(下拉刷新时调用)。
  37. void clear() => _store.clear();
  38. }
  39. class _CacheEntry {
  40. final dynamic data;
  41. final DateTime expiresAt;
  42. _CacheEntry(this.data, this.expiresAt);
  43. bool get isExpired => DateTime.now().isAfter(expiresAt);
  44. }