5.3 本地存储

Flutter 提供了多种本地存储方案,从简单的键值对到高性能对象数据库,按数据复杂度和性能需求选择合适方案。


一、shared_preferences(键值对)

适合存储简单配置、用户偏好、Token 等轻量数据。

yaml 复制代码
dependencies:
  shared_preferences: ^2.2.2
dart 复制代码
class PreferencesService {
  static SharedPreferences? _prefs;

  static Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  // Token 管理
  static Future<void> saveToken(String token) =>
      _prefs!.setString('access_token', token);
  static String? getToken() => _prefs!.getString('access_token');
  static Future<void> clearToken() => _prefs!.remove('access_token');

  // 用户偏好
  static Future<void> setDarkMode(bool value) =>
      _prefs!.setBool('dark_mode', value);
  static bool getDarkMode() => _prefs!.getBool('dark_mode') ?? false;

  static Future<void> setLanguage(String locale) =>
      _prefs!.setString('language', locale);
  static String getLanguage() => _prefs!.getString('language') ?? 'zh';

  // 复杂对象(JSON 序列化)
  static Future<void> saveUser(User user) =>
      _prefs!.setString('user', jsonEncode(user.toJson()));
  static User? getUser() {
    final str = _prefs!.getString('user');
    if (str == null) return null;
    return User.fromJson(jsonDecode(str));
  }

  static Future<void> clear() => _prefs!.clear();
}

二、Hive(高性能 NoSQL)

Hive 是纯 Dart 实现的轻量级 NoSQL 数据库,性能优秀,支持加密。

yaml 复制代码
dependencies:
  hive_flutter: ^1.1.0

dev_dependencies:
  hive_generator: ^2.0.1
  build_runner: ^2.4.0

2.1 注册自定义对象

dart 复制代码
import 'package:hive_flutter/hive_flutter.dart';

part 'product.g.dart';

@HiveType(typeId: 0)  // typeId 全局唯一
class Product extends HiveObject {
  @HiveField(0)
  final int id;

  @HiveField(1)
  final String name;

  @HiveField(2)
  final double price;

  @HiveField(3)
  final bool isFavorited;

  Product({
    required this.id,
    required this.name,
    required this.price,
    this.isFavorited = false,
  });
}

// 初始化
Future<void> main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(ProductAdapter()); // 注册生成的 Adapter
  await Hive.openBox<Product>('products');
  await Hive.openBox('settings');
  runApp(const MyApp());
}

2.2 CRUD 操作

dart 复制代码
class ProductCacheService {
  Box<Product> get _box => Hive.box<Product>('products');

  // 写入
  Future<void> saveProduct(Product product) =>
      _box.put(product.id.toString(), product);

  Future<void> saveAll(List<Product> products) async {
    final map = {for (final p in products) p.id.toString(): p};
    await _box.putAll(map);
  }

  // 读取
  Product? getProduct(int id) => _box.get(id.toString());
  List<Product> getAll() => _box.values.toList();

  // 查询
  List<Product> getFavorites() =>
      _box.values.where((p) => p.isFavorited).toList();

  // 删除
  Future<void> deleteProduct(int id) => _box.delete(id.toString());
  Future<void> clearAll() => _box.clear();
}

2.3 监听变化(响应式)

dart 复制代码
ValueListenableBuilder<Box<Product>>(
  valueListenable: Hive.box<Product>('products').listenable(),
  builder: (context, box, _) {
    final products = box.values.toList();
    return ProductList(products: products);
  },
)

三、sqflite(关系型数据库)

适合需要关联查询、事务、复杂查询的场景。

yaml 复制代码
dependencies:
  sqflite: ^2.3.0
  path: ^1.8.3
dart 复制代码
class DatabaseService {
  static Database? _db;

  static Future<Database> get database async {
    _db ??= await _initDatabase();
    return _db!;
  }

  static Future<Database> _initDatabase() async {
    final dbPath = await getDatabasesPath();
    final path = join(dbPath, 'app.db');

    return openDatabase(
      path,
      version: 2,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  static Future<void> _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE orders (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER NOT NULL,
        total_amount REAL NOT NULL,
        status TEXT NOT NULL DEFAULT 'pending',
        created_at TEXT NOT NULL,
        FOREIGN KEY (user_id) REFERENCES users (id)
      )
    ''');

    await db.execute('''
      CREATE TABLE order_items (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        order_id INTEGER NOT NULL,
        product_id INTEGER NOT NULL,
        quantity INTEGER NOT NULL,
        price REAL NOT NULL,
        FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE
      )
    ''');

    await db.execute('CREATE INDEX idx_orders_user ON orders(user_id)');
  }

  static Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
    if (oldVersion < 2) {
      await db.execute('ALTER TABLE orders ADD COLUMN note TEXT');
    }
  }

  // CRUD
  static Future<int> insertOrder(Order order) async {
    final db = await database;
    return db.transaction((txn) async {
      final orderId = await txn.insert('orders', order.toDbMap());
      for (final item in order.items) {
        await txn.insert('order_items', {
          ...item.toDbMap(),
          'order_id': orderId,
        });
      }
      return orderId;
    });
  }

  static Future<List<Order>> getOrders(int userId) async {
    final db = await database;
    final maps = await db.rawQuery('''
      SELECT o.*, COUNT(oi.id) as item_count
      FROM orders o
      LEFT JOIN order_items oi ON o.id = oi.order_id
      WHERE o.user_id = ?
      GROUP BY o.id
      ORDER BY o.created_at DESC
      LIMIT 50
    ''', [userId]);
    return maps.map(Order.fromDbMap).toList();
  }
}

四、Isar(高性能现代 NoSQL)

Isar 是新一代本地数据库,比 Hive 性能更强,支持全文搜索和复杂查询。

yaml 复制代码
dependencies:
  isar: ^3.1.0
  isar_flutter_libs: ^3.1.0
  path_provider: ^2.0.0

dev_dependencies:
  isar_generator: ^3.1.0
  build_runner: ^2.4.0
dart 复制代码
part 'product.g.dart';

@collection
class Product {
  Id id = Isar.autoIncrement;

  @Index(type: IndexType.value)
  late String name;

  late double price;
  late bool isFavorited;

  @Index(type: IndexType.fullText)
  late String description; // 支持全文搜索
}

// 初始化
final isar = await Isar.open([ProductSchema], directory: dir.path);

// 写入(极快)
await isar.writeTxn(() async {
  await isar.products.putAll(products);
});

// 查询(类型安全的查询 DSL)
final expensiveProducts = await isar.products
    .filter()
    .priceGreaterThan(100)
    .and()
    .isFavoritedEqualTo(true)
    .sortByPriceDesc()
    .limit(20)
    .findAll();

// 全文搜索
final results = await isar.products
    .filter()
    .descriptionContains('flutter', caseSensitive: false)
    .findAll();

// 实时监听
isar.products.watchLazy().listen((_) {
  // 数据变化,刷新 UI
});

五、文件读写与缓存策略

dart 复制代码
class FileStorageService {
  static Future<Directory> get _cacheDir async =>
      (await getApplicationCacheDirectory());
  static Future<Directory> get _docDir async =>
      (await getApplicationDocumentsDirectory());

  // 写入文件
  static Future<void> writeJson(String filename, Map<String, dynamic> data) async {
    final dir = await _cacheDir;
    final file = File('${dir.path}/$filename.json');
    await file.writeAsString(jsonEncode(data));
  }

  // 读取文件
  static Future<Map<String, dynamic>?> readJson(String filename) async {
    try {
      final dir = await _cacheDir;
      final file = File('${dir.path}/$filename.json');
      if (!await file.exists()) return null;

      // 检查缓存是否过期
      final stat = await file.stat();
      if (DateTime.now().difference(stat.modified) > const Duration(hours: 1)) {
        await file.delete();
        return null;
      }

      return jsonDecode(await file.readAsString());
    } catch (_) {
      return null;
    }
  }

  // 清理过期缓存
  static Future<void> clearExpiredCache() async {
    final dir = await _cacheDir;
    final files = await dir.list().toList();
    for (final entity in files) {
      if (entity is File) {
        final stat = await entity.stat();
        if (DateTime.now().difference(stat.modified) > const Duration(days: 7)) {
          await entity.delete();
        }
      }
    }
  }
}

小结

方案 数据类型 性能 适用场景
shared_preferences 键值对 配置、Token、用户设置
Hive 对象/键值 极快 缓存、列表数据
sqflite 关系型 复杂关联、事务数据
Isar 对象 极快 大量数据、全文搜索
文件系统 任意 图片缓存、JSON 缓存

👉 下一章:六、主题与国际化(i18n)

相关推荐
空中海5 小时前
9.4 推送通知
flutter
星释5 小时前
鸿蒙Flutter实战:30.在Pub上发布鸿蒙化插件
flutter·harmonyos·鸿蒙
nice先生的狂想曲5 小时前
flutter布局(列表组件)
flutter
见山是山-见水是水5 小时前
鸿蒙flutter第三方库适配 - 动态工作流
flutter·华为·harmonyos
yeziyfx6 小时前
Flutter SingleChildScrollView内部ListView滑动不了
flutter
Zender Han6 小时前
VS Code 开发 Flutter 常用快捷键和插件工具详解
android·vscode·flutter·ios
于慨6 小时前
flutter安卓调试工具
android·flutter
见山是山-见水是水6 小时前
鸿蒙flutter第三方库适配 - 动态布局库
flutter·华为·harmonyos
欧达克6 小时前
vibe coding:2 天用 AI 鼓捣一个 APP
flutter·app