Skip to content

Flutter 持久化存储

持久化存储概述

在 Flutter 应用中,持久化存储是指将数据保存在设备上,以便在应用重启后仍然可以访问。Flutter 提供了多种持久化存储方案,适用于不同的使用场景。

存储方案

1. SharedPreferences

SharedPreferences 是一种轻量级的键值对存储方案,适用于存储简单的数据,如用户偏好设置、令牌等。

安装

bash
flutter pub add shared_preferences

示例

dart
import 'package:shared_preferences/shared_preferences.dart';

// 保存数据
Future<void> saveData() async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setString('username', 'flutter');
  await prefs.setInt('age', 3);
  await prefs.setBool('isLoggedIn', true);
  await prefs.setDouble('score', 99.5);
  await prefs.setStringList('items', ['item1', 'item2', 'item3']);
}

// 读取数据
Future<void> loadData() async {
  final prefs = await SharedPreferences.getInstance();
  final username = prefs.getString('username');
  final age = prefs.getInt('age');
  final isLoggedIn = prefs.getBool('isLoggedIn');
  final score = prefs.getDouble('score');
  final items = prefs.getStringList('items');
  
  print('Username: $username');
  print('Age: $age');
  print('Is Logged In: $isLoggedIn');
  print('Score: $score');
  print('Items: $items');
}

// 删除数据
Future<void> removeData() async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.remove('username');
  // 清除所有数据
  // await prefs.clear();
}

2. 本地文件存储

本地文件存储适用于存储较大的数据,如图片、音频、JSON 数据等。

示例

dart
import 'dart:io';
import 'dart:convert';
import 'package:path_provider/path_provider.dart';

// 保存数据到文件
Future<void> saveToFile() async {
  final directory = await getApplicationDocumentsDirectory();
  final file = File('${directory.path}/data.json');
  
  final data = {
    'username': 'flutter',
    'age': 3,
    'isLoggedIn': true,
  };
  
  await file.writeAsString(jsonEncode(data));
}

// 从文件读取数据
Future<void> loadFromFile() async {
  final directory = await getApplicationDocumentsDirectory();
  final file = File('${directory.path}/data.json');
  
  if (await file.exists()) {
    final contents = await file.readAsString();
    final data = jsonDecode(contents);
    print(data);
  } else {
    print('File does not exist');
  }
}

// 删除文件
Future<void> deleteFile() async {
  final directory = await getApplicationDocumentsDirectory();
  final file = File('${directory.path}/data.json');
  
  if (await file.exists()) {
    await file.delete();
  }
}

3. SQLite

SQLite 是一种关系型数据库,适用于存储结构化数据,如用户信息、产品数据等。

安装

bash
flutter pub add sqflite path

示例

dart
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DatabaseHelper {
  static Database? _database;

  Future<Database> get database async {
    if (_database != null) return _database!;
    
    _database = await initDatabase();
    return _database!;
  }

  Future<Database> initDatabase() async {
    final path = join(await getDatabasesPath(), 'app_database.db');
    
    return await openDatabase(
      path,
      version: 1,
      onCreate: (db, version) {
        return db.execute(
          'CREATE TABLE users(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, email TEXT)',
        );
      },
    );
  }

  // 插入数据
  Future<void> insertUser(Map<String, dynamic> user) async {
    final db = await database;
    await db.insert('users', user, conflictAlgorithm: ConflictAlgorithm.replace);
  }

  // 查询所有用户
  Future<List<Map<String, dynamic>>> getUsers() async {
    final db = await database;
    return await db.query('users');
  }

  // 根据ID查询用户
  Future<Map<String, dynamic>?> getUser(int id) async {
    final db = await database;
    final users = await db.query('users', where: 'id = ?', whereArgs: [id]);
    return users.isNotEmpty ? users.first : null;
  }

  // 更新用户
  Future<void> updateUser(int id, Map<String, dynamic> user) async {
    final db = await database;
    await db.update('users', user, where: 'id = ?', whereArgs: [id]);
  }

  // 删除用户
  Future<void> deleteUser(int id) async {
    final db = await database;
    await db.delete('users', where: 'id = ?', whereArgs: [id]);
  }
}

// 使用
final dbHelper = DatabaseHelper();

// 插入用户
await dbHelper.insertUser({'name': 'Flutter', 'email': 'flutter@example.com'});

// 查询所有用户
final users = await dbHelper.getUsers();
print(users);

// 根据ID查询用户
final user = await dbHelper.getUser(1);
print(user);

// 更新用户
await dbHelper.updateUser(1, {'name': 'Flutter Updated', 'email': 'updated@example.com'});

// 删除用户
await dbHelper.deleteUser(1);

4. Hive

Hive 是一个轻量级的 NoSQL 数据库,适用于存储复杂的对象,性能比 SQLite 更好。

安装

bash
flutter pub add hive hive_flutter

示例

dart
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';

// 初始化 Hive
void initHive() async {
  await Hive.initFlutter();
  // 注册适配器(如果需要存储自定义对象)
  // Hive.registerAdapter(UserAdapter());
  await Hive.openBox('userBox');
}

// 保存数据
void saveUser() {
  final box = Hive.box('userBox');
  box.put('user', {
    'name': 'Flutter',
    'email': 'flutter@example.com',
    'age': 3,
  });
  
  // 保存列表
  box.put('items', ['item1', 'item2', 'item3']);
}

// 读取数据
void loadUser() {
  final box = Hive.box('userBox');
  final user = box.get('user');
  final items = box.get('items');
  
  print('User: $user');
  print('Items: $items');
}

// 删除数据
void removeUser() {
  final box = Hive.box('userBox');
  box.delete('user');
  // 清除所有数据
  // box.clear();
}

// 存储自定义对象
@HiveType(typeId: 0)
class User extends HiveObject {
  @HiveField(0)
  String name;
  
  @HiveField(1)
  String email;
  
  @HiveField(2)
  int age;
  
  User({required this.name, required this.email, required this.age});
}

// 生成适配器
// 运行命令: flutter pub run build_runner build

// 使用自定义对象
void saveCustomUser() {
  final box = Hive.box<User>('userBox');
  final user = User(name: 'Flutter', email: 'flutter@example.com', age: 3);
  box.put('user', user);
}

void loadCustomUser() {
  final box = Hive.box<User>('userBox');
  final user = box.get('user');
  print('User: ${user?.name}, ${user?.email}, ${user?.age}');
}

5. 其他存储方案

Firebase Firestore

适用于需要云同步的应用。

安装

bash
flutter pub add firebase_core firebase_firestore

GraphQL

适用于需要与 GraphQL API 交互的应用。

安装

bash
flutter pub add graphql_flutter

存储方案对比

方案优点缺点适用场景
SharedPreferences简单易用,适合存储小数据存储容量有限,不适合复杂数据存储用户偏好设置、令牌等
本地文件存储适合存储大文件,如图片、音频等需要手动管理文件,不适合结构化数据存储图片、音频、JSON 数据等
SQLite适合存储结构化数据,支持 SQL 查询学习曲线较陡,性能可能不如 NoSQL存储用户信息、产品数据等
Hive性能好,适合存储复杂对象功能相对简单,不支持 SQL 查询存储复杂对象,如用户配置、应用状态等
Firebase Firestore云同步,实时数据需要网络连接,可能产生费用需要云同步的应用

存储最佳实践

  1. 根据数据类型选择合适的存储方案

    • 简单键值对:SharedPreferences
    • 大文件:本地文件存储
    • 结构化数据:SQLite
    • 复杂对象:Hive
    • 需要云同步:Firebase Firestore
  2. 合理管理存储空间

    • 定期清理不需要的数据
    • 对大文件进行压缩
    • 使用分页加载减少内存使用
  3. 数据安全

    • 敏感数据加密存储
    • 不要在本地存储密码等敏感信息
    • 使用安全的存储机制,如 Keychain (iOS) 或 Keystore (Android)
  4. 错误处理

    • 处理存储操作可能出现的错误
    • 提供适当的错误提示
  5. 备份与恢复

    • 对于重要数据,提供备份和恢复功能
    • 考虑使用云存储作为备份

总结

Flutter 提供了多种持久化存储方案,每种方案都有其适用场景。选择合适的存储方案并合理使用,可以使应用的数据管理更加高效和可靠。在实际开发中,根据数据的类型、大小和使用场景选择最适合的存储方案是非常重要的。

基于 VitePress 的本地知识库