Flutter本地存储完全指南
Flutter本地存储完全指南引言在移动应用开发中本地存储是必不可少的功能用于持久化保存用户数据、配置信息、缓存内容等。Flutter提供了多种本地存储方案每种方案适用于不同的场景。本文将详细介绍Flutter中常用的本地存储方式及其最佳实践。本地存储方案对比方案适用场景数据类型数据大小优点缺点SharedPreferences简单键值对基本类型小简单易用仅支持基本类型Hive对象存储任意对象中高性能、类型安全需要定义AdapterSQFlite关系型数据库结构化数据大支持复杂查询学习成本高File文件存储任意数据大灵活需要手动管理SharedPreferences安装与配置dependencies: shared_preferences: ^2.2.2基本用法import package:shared_preferences/shared_preferences.dart; class PreferencesService { Futurevoid saveString(String key, String value) async { final prefs await SharedPreferences.getInstance(); await prefs.setString(key, value); } FutureString? getString(String key) async { final prefs await SharedPreferences.getInstance(); return prefs.getString(key); } Futurevoid saveInt(String key, int value) async { final prefs await SharedPreferences.getInstance(); await prefs.setInt(key, value); } Futureint? getInt(String key) async { final prefs await SharedPreferences.getInstance(); return prefs.getInt(key); } Futurevoid saveBool(String key, bool value) async { final prefs await SharedPreferences.getInstance(); await prefs.setBool(key, value); } Futurebool? getBool(String key) async { final prefs await SharedPreferences.getInstance(); return prefs.getBool(key); } Futurevoid remove(String key) async { final prefs await SharedPreferences.getInstance(); await prefs.remove(key); } Futurevoid clear() async { final prefs await SharedPreferences.getInstance(); await prefs.clear(); } }实际应用// 保存用户偏好设置 final service PreferencesService(); await service.saveString(username, john_doe); await service.saveBool(dark_mode, true); await service.saveInt(notifications_count, 5); // 读取用户偏好设置 final username await service.getString(username); final darkMode await service.getBool(dark_mode) ?? false; final count await service.getInt(notifications_count) ?? 0;Hive安装与配置dependencies: hive: ^2.2.3 hive_flutter: ^1.1.0 dev_dependencies: hive_generator: ^1.1.5 build_runner: ^2.4.4创建数据模型import package:hive/hive.dart; part user.g.dart; HiveType(typeId: 0) class User { HiveField(0) final String id; HiveField(1) final String name; HiveField(2) final String email; HiveField(3) final int age; HiveField(4) final DateTime createdAt; User({ required this.id, required this.name, required this.email, required this.age, required this.createdAt, }); }生成Adapter运行以下命令生成Adapterflutter packages pub run build_runner build初始化Hiveimport package:hive/hive.dart; import package:hive_flutter/hive_flutter.dart; import user.dart; void main() async { await Hive.initFlutter(); Hive.registerAdapter(UserAdapter()); await Hive.openBoxUser(users); runApp(const MyApp()); }基本操作class HiveService { final BoxUser _userBox; HiveService(this._userBox); // 添加用户 Futurevoid addUser(User user) async { await _userBox.put(user.id, user); } // 获取用户 User? getUser(String id) { return _userBox.get(id); } // 获取所有用户 ListUser getAllUsers() { return _userBox.values.toList(); } // 更新用户 Futurevoid updateUser(User user) async { await _userBox.put(user.id, user); } // 删除用户 Futurevoid deleteUser(String id) async { await _userBox.delete(id); } // 查询用户 ListUser searchUsers(String query) { return _userBox.values .where((user) user.name.toLowerCase().contains(query.toLowerCase()) || user.email.toLowerCase().contains(query.toLowerCase()) ) .toList(); } }使用示例// 创建HiveService final userBox Hive.boxUser(users); final service HiveService(userBox); // 添加用户 final user User( id: 1, name: John Doe, email: johnexample.com, age: 30, createdAt: DateTime.now(), ); await service.addUser(user); // 获取用户 final retrievedUser service.getUser(1); print(retrievedUser?.name); // John Doe // 查询用户 final results service.searchUsers(john); print(results.length); // 1SQFlite安装与配置dependencies: sqflite: ^2.3.2 path_provider: ^2.1.1创建数据库import package:sqflite/sqflite.dart; import package:path/path.dart; import package:path_provider/path_provider.dart; class DatabaseHelper { static Database? _database; FutureDatabase get database async { if (_database ! null) return _database!; _database await _initDatabase(); return _database!; } FutureDatabase _initDatabase() async { final documentsDirectory await getApplicationDocumentsDirectory(); final path join(documentsDirectory.path, app_database.db); return await openDatabase( path, version: 1, onCreate: _onCreate, onUpgrade: _onUpgrade, ); } Futurevoid _onCreate(Database db, int version) async { await db.execute( CREATE TABLE users ( id TEXT PRIMARY KEY, name TEXT NOT NULL, email TEXT NOT NULL UNIQUE, age INTEGER, created_at TEXT NOT NULL ) ); await db.execute( CREATE TABLE posts ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, title TEXT NOT NULL, content TEXT, created_at TEXT NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id) ) ); } Futurevoid _onUpgrade(Database db, int oldVersion, int newVersion) async { // 数据库升级逻辑 if (oldVersion 2) { // 添加新字段或表 } } }CRUD操作class UserDao { final Database _db; UserDao(this._db); Futurevoid insertUser(User user) async { await _db.insert( users, { id: user.id, name: user.name, email: user.email, age: user.age, created_at: user.createdAt.toIso8601String(), }, conflictAlgorithm: ConflictAlgorithm.replace, ); } FutureUser? getUser(String id) async { final maps await _db.query( users, where: id ?, whereArgs: [id], ); if (maps.isNotEmpty) { return User.fromMap(maps.first); } return null; } FutureListUser getAllUsers() async { final maps await _db.query(users); return maps.map((map) User.fromMap(map)).toList(); } Futureint updateUser(User user) async { return await _db.update( users, { name: user.name, email: user.email, age: user.age, }, where: id ?, whereArgs: [user.id], ); } Futureint deleteUser(String id) async { return await _db.delete( users, where: id ?, whereArgs: [id], ); } FutureListUser getUsersByAge(int minAge, int maxAge) async { final maps await _db.query( users, where: age BETWEEN ? AND ?, whereArgs: [minAge, maxAge], orderBy: age ASC, ); return maps.map((map) User.fromMap(map)).toList(); } }User模型class User { final String id; final String name; final String email; final int? age; final DateTime createdAt; User({ required this.id, required this.name, required this.email, this.age, required this.createdAt, }); factory User.fromMap(MapString, dynamic map) { return User( id: map[id] as String, name: map[name] as String, email: map[email] as String, age: map[age] as int?, createdAt: DateTime.parse(map[created_at] as String), ); } MapString, dynamic toMap() { return { id: id, name: name, email: email, age: age, created_at: createdAt.toIso8601String(), }; } }使用示例// 获取数据库实例 final dbHelper DatabaseHelper(); final db await dbHelper.database; final userDao UserDao(db); // 插入用户 final user User( id: 1, name: John Doe, email: johnexample.com, age: 30, createdAt: DateTime.now(), ); await userDao.insertUser(user); // 查询用户 final retrievedUser await userDao.getUser(1); print(retrievedUser?.name); // John Doe // 查询年龄在20-35岁之间的用户 final users await userDao.getUsersByAge(20, 35); print(users.length);File存储基本文件操作import dart:io; import package:path_provider/path_provider.dart; class FileStorageService { FutureString get _localPath async { final directory await getApplicationDocumentsDirectory(); return directory.path; } FutureFile _localFile(String filename) async { final path await _localPath; return File($path/$filename); } Futurevoid writeString(String filename, String content) async { final file await _localFile(filename); await file.writeAsString(content); } FutureString readString(String filename) async { try { final file await _localFile(filename); return await file.readAsString(); } catch (e) { return ; } } Futurevoid writeBytes(String filename, Listint bytes) async { final file await _localFile(filename); await file.writeAsBytes(bytes); } FutureListint readBytes(String filename) async { try { final file await _localFile(filename); return await file.readAsBytes(); } catch (e) { return []; } } Futurebool fileExists(String filename) async { final file await _localFile(filename); return await file.exists(); } Futurevoid deleteFile(String filename) async { final file await _localFile(filename); if (await file.exists()) { await file.delete(); } } }保存JSON数据import dart:convert; final storage FileStorageService(); // 保存JSON数据 final user { id: 1, name: John Doe, email: johnexample.com, }; final jsonString json.encode(user); await storage.writeString(user.json, jsonString); // 读取JSON数据 final jsonData await storage.readString(user.json); final userMap json.decode(jsonData) as MapString, dynamic; print(userMap[name]); // John Doe选择合适的存储方案选择指南数据量小 数据量大 ↓ ↓ 简单键值对 SharedPreferences SQFlite 对象存储 Hive SQFlite 文件存储 File File推荐使用场景场景推荐方案用户设置/偏好SharedPreferences小型对象存储Hive复杂查询/关系数据SQFlite文件/图片/缓存File性能优化批量操作// SQFlite批量插入 Futurevoid insertUsers(ListUser users) async { final db await database; final batch db.batch(); for (var user in users) { batch.insert(users, user.toMap()); } await batch.commit(noResult: true); }异步操作// 避免阻塞UI线程 Futurevoid loadData() async { // 使用isolate或后台线程处理大量数据 final data await compute(_parseData, rawData); setState(() { _items data; }); } ListItem _parseData(String rawData) { // 耗时的数据解析 return rawData.split(,).map((e) Item(e)).toList(); }缓存策略class CacheService { final Duration _expiryDuration const Duration(hours: 1); Futurevoid cacheData(String key, dynamic data) async { final cache { data: data, timestamp: DateTime.now().toIso8601String(), }; await _preferences.setString(key, json.encode(cache)); } Futuredynamic? getCachedData(String key) async { final cacheString await _preferences.getString(key); if (cacheString null) return null; final cache json.decode(cacheString) as MapString, dynamic; final timestamp DateTime.parse(cache[timestamp] as String); if (DateTime.now().difference(timestamp) _expiryDuration) { await _preferences.remove(key); return null; } return cache[data]; } }数据迁移数据库版本迁移Futurevoid _onUpgrade(Database db, int oldVersion, int newVersion) async { if (oldVersion 1 newVersion 2) { // 添加新字段 await db.execute(ALTER TABLE users ADD COLUMN phone TEXT); } if (oldVersion 2 newVersion 3) { // 创建新表 await db.execute( CREATE TABLE settings ( id TEXT PRIMARY KEY, key TEXT UNIQUE, value TEXT ) ); } }安全注意事项1. 敏感数据加密import package:encrypt/encrypt.dart; class SecureStorage { final String _key your-encryption-key; String encrypt(String plainText) { final key Key.fromUtf8(_key.padRight(32)); final iv IV.fromLength(16); final encrypter Encrypter(AES(key)); return encrypter.encrypt(plainText, iv: iv).base64; } String decrypt(String encryptedText) { final key Key.fromUtf8(_key.padRight(32)); final iv IV.fromLength(16); final encrypter Encrypter(AES(key)); return encrypter.decrypt64(encryptedText, iv: iv); } }2. 避免存储敏感信息// 错误做法存储密码 await prefs.setString(password, secret123); // 正确做法存储token或使用Keychain/Keystore await prefs.setString(auth_token, jwt-token-here);总结Flutter提供了多种本地存储方案选择合适的方案取决于你的具体需求SharedPreferences适合简单的键值对存储如用户偏好设置Hive适合对象存储高性能且类型安全SQFlite适合复杂的关系型数据存储支持SQL查询File适合文件存储如图片、缓存文件核心要点根据数据类型和大小选择合适的存储方案使用异步操作避免阻塞UI线程对敏感数据进行加密处理考虑数据迁移和版本管理掌握这些存储方案后你可以根据项目需求灵活选择合适的本地存储策略。