Flutter 离线缓存方案:使用 Hive 存储接口数据

在 Flutter 中实现离线缓存的核心思路是:

  1. 优先读取本地缓存数据
  2. 当网络请求成功后更新缓存
  3. 缓存过期时自动刷新
实现步骤
1. 添加依赖 (pubspec.yaml)
dependencies:
  hive: ^2.2.3
  hive_flutter: ^1.1.0
  http: ^1.1.0
  path_provider: ^2.1.1

2. 初始化 Hive
import 'package:hive_flutter/hive_flutter.dart';

Future<void> initCache() async {
  await Hive.initFlutter();
  await Hive.openBox('api_cache');  // 创建缓存盒子
}

3. 缓存管理类
class CacheManager {
  static const _cacheBox = 'api_cache';
  static const _expiryKey = 'expiry_';  // 过期时间前缀
  static const _defaultExpiry = Duration(hours: 1);  // 默认1小时过期

  // 保存数据
  static Future<void> saveData({
    required String key,
    required dynamic data,
    Duration? expiry,
  }) async {
    final box = await Hive.openBox(_cacheBox);
    await box.put(key, data);
    await box.put(
      '$_expiryKey$key',
      DateTime.now().add(expiry ?? _defaultExpiry).millisecondsSinceEpoch,
    );
  }

  // 获取数据(带过期检查)
  static Future<dynamic> getData(String key) async {
    final box = await Hive.openBox(_cacheBox);
    final expiry = box.get('$_expiryKey$key', defaultValue: 0) as int;
    
    if (expiry > DateTime.now().millisecondsSinceEpoch) {
      return box.get(key);  // 返回有效缓存
    }
    return null;  // 缓存已过期
  }

  // 清除缓存
  static Future<void> clearCache(String key) async {
    final box = await Hive.openBox(_cacheBox);
    await box.delete(key);
    await box.delete('$_expiryKey$key');
  }
}

4. 网络请求封装
class ApiService {
  static Future<dynamic> fetchData({
    required String url,
    bool forceRefresh = false,  // 强制刷新
  }) async {
    final cacheKey = url;  // 使用URL作为缓存键
    
    // 尝试读取缓存
    if (!forceRefresh) {
      final cachedData = await CacheManager.getData(cacheKey);
      if (cachedData != null) return cachedData;
    }

    // 发起网络请求
    final response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      final data = jsonDecode(response.body);
      
      // 更新缓存
      await CacheManager.saveData(key: cacheKey, data: data);
      return data;
    }
    throw Exception('请求失败: ${response.statusCode}');
  }
}

5. 使用示例
// 在页面中调用
Future<void> loadData() async {
  try {
    final data = await ApiService.fetchData(
      url: 'https://api.example.com/data',
    );
    // 使用数据更新UI
  } catch (e) {
    // 处理错误
  }
}

// 强制刷新
void refreshData() {
  ApiService.fetchData(
    url: 'https://api.example.com/data',
    forceRefresh: true,
  );
}

优化建议
  1. 缓存策略

    • 添加缓存大小限制(如最多100条记录)
    • 实现 LRU(最近最少使用)淘汰策略
    void _checkCacheLimit() async {
      final box = await Hive.openBox('api_cache');
      if (box.length > 100) {
        // 实现淘汰逻辑
      }
    }
    

  2. 数据类型支持

    • 使用 Hive TypeAdapter 支持自定义模型
    @HiveType(typeId: 0)
    class UserModel extends HiveObject {
      @HiveField(0)
      final String name;
      
      @HiveField(1)
      final int age;
    }
    

  3. 错误处理

    • 网络异常时返回最近的有效缓存
    • 添加缓存失效时的回退机制
方案优势
  1. 高性能:Hive 基于二进制存储,读取速度比 SQLite 快 2-3 倍
  2. 零依赖:无需原生依赖,纯 Dart 实现
  3. 类型安全:支持强类型数据模型
  4. 自动加密:可通过 hive_flutter 集成 AES 加密

注意:对于敏感数据,建议使用 flutter_secure_storage 配合加密密钥增强安全性

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐