Flutter 本地存储完全指南
·
Flutter 本地存储完全指南
引言
本地存储是移动应用开发中不可或缺的一部分,它允许应用在设备上持久化数据。Flutter 提供了多种本地存储方案,本文将深入探讨各种存储方式和最佳实践。
存储方案概述
| 方案 | 适用场景 | 数据类型 | 大小限制 |
|---|---|---|---|
| SharedPreferences | 简单键值对 | 基本类型 | 较小 |
| GetStorage | 简单键值对 | 基本类型 | 较大 |
| SQLite | 复杂数据 | 关系型数据 | 较大 |
| Hive | NoSQL 数据库 | 对象 | 较大 |
| File | 文件存储 | 任意文件 | 较大 |
高级技巧一:SharedPreferences
基本用法
import 'package:shared_preferences/shared_preferences.dart';
// 保存数据
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('counter', 42);
await prefs.setString('username', 'John');
await prefs.setBool('isDarkMode', true);
// 读取数据
int? counter = prefs.getInt('counter');
String? username = prefs.getString('username');
bool? isDarkMode = prefs.getBool('isDarkMode');
// 删除数据
await prefs.remove('counter');
await prefs.clear();
封装存储服务
class PreferencesService {
static late SharedPreferences _prefs;
static Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
}
static int get counter => _prefs.getInt('counter') ?? 0;
static set counter(int value) => _prefs.setInt('counter', value);
static String get username => _prefs.getString('username') ?? '';
static set username(String value) => _prefs.setString('username', value);
static bool get isDarkMode => _prefs.getBool('isDarkMode') ?? false;
static set isDarkMode(bool value) => _prefs.setBool('isDarkMode', value);
}
高级技巧二:GetStorage
基本用法
import 'package:get_storage/get_storage.dart';
// 初始化
await GetStorage.init();
final box = GetStorage();
// 保存数据
box.write('user', {'name': 'John', 'age': 30});
box.write('counter', 42);
// 读取数据
Map<String, dynamic>? user = box.read('user');
int counter = box.read('counter') ?? 0;
// 删除数据
box.remove('user');
box.erase();
监听变化
box.listenKey('counter', (value) {
print('Counter changed: $value');
});
高级技巧三:Hive 数据库
配置 Hive
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
// 初始化
await Hive.initFlutter();
// 注册适配器
Hive.registerAdapter(UserAdapter());
// 打开盒子
final box = await Hive.openBox<User>('users');
创建数据模型
part 'user.g.dart';
@HiveType(typeId: 0)
class User {
@HiveField(0)
final String name;
@HiveField(1)
final int age;
@HiveField(2)
final String email;
User({required this.name, required this.age, required this.email});
}
操作数据
// 添加数据
final user = User(name: 'John', age: 30, email: 'john@example.com');
await box.add(user);
// 获取数据
User? user = box.getAt(0);
User? userByKey = box.get('user1');
// 更新数据
user.name = 'John Updated';
await user.save();
// 删除数据
await box.deleteAt(0);
await box.clear();
高级技巧四:SQLite 数据库
使用 moor
import 'package:moor/moor.dart';
import 'package:moor_flutter/moor_flutter.dart';
// 创建数据库
class AppDatabase extends _$AppDatabase {
AppDatabase() : super(FlutterQueryExecutor.inDatabaseFolder(path: 'db.sqlite'));
@override
int get schemaVersion => 1;
// 表定义
final users = Table('users');
final id = users.int().autoIncrement();
final name = users.text();
final age = users.integer();
}
// 操作数据
final db = AppDatabase();
// 插入
await db.into(db.users).insert(UsersCompanion.insert(
name: 'John',
age: 30,
));
// 查询
final users = await db.select(db.users).get();
final user = await (db.select(db.users)..where((u) => u.id.equals(1))).getSingle();
// 更新
await (db.update(db.users)..where((u) => u.id.equals(1))).write(UsersCompanion(
name: Value('John Updated'),
));
// 删除
await (db.delete(db.users)..where((u) => u.id.equals(1))).go();
高级技巧五:文件存储
基本文件操作
import 'dart:io';
import 'package:path_provider/path_provider.dart';
// 获取目录
final directory = await getApplicationDocumentsDirectory();
final filePath = '${directory.path}/data.txt';
// 写入文件
await File(filePath).writeAsString('Hello, World!');
// 读取文件
String content = await File(filePath).readAsString();
// 删除文件
await File(filePath).delete();
序列化对象
import 'dart:convert';
// 序列化
final user = {'name': 'John', 'age': 30};
final jsonString = jsonEncode(user);
await File(filePath).writeAsString(jsonString);
// 反序列化
final jsonString = await File(filePath).readAsString();
final user = jsonDecode(jsonString) as Map<String, dynamic>;
实战案例:主题状态持久化
class ThemeService {
static const String _key = 'theme_mode';
static Future<ThemeMode> getThemeMode() async {
final prefs = await SharedPreferences.getInstance();
final mode = prefs.getString(_key);
switch (mode) {
case 'dark':
return ThemeMode.dark;
case 'light':
return ThemeMode.light;
default:
return ThemeMode.system;
}
}
static Future<void> setThemeMode(ThemeMode mode) async {
final prefs = await SharedPreferences.getInstance();
String value;
switch (mode) {
case ThemeMode.dark:
value = 'dark';
break;
case ThemeMode.light:
value = 'light';
break;
default:
value = 'system';
}
await prefs.setString(_key, value);
}
}
实战案例:用户数据持久化
class UserRepository {
final Box<User> _box;
UserRepository(this._box);
Future<void> saveUser(User user) async {
await _box.put(user.id.toString(), user);
}
User? getUser(String id) {
return _box.get(id);
}
Future<void> deleteUser(String id) async {
await _box.delete(id);
}
List<User> getAllUsers() {
return _box.values.toList();
}
}
常见问题与解决方案
Q1:如何处理数据迁移?
A:使用 Hive 的迁移机制:
final box = await Hive.openBox('data', migration: (oldVersion, newVersion) {
if (oldVersion == 1) {
// 迁移逻辑
}
});
Q2:如何加密数据?
A:使用加密包:
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:encrypt/encrypt.dart';
// 创建加密适配器
final encryptionKey = Hive.generateSecureKey();
final box = await Hive.openBox('secureBox', encryptionCipher: HiveAesCipher(encryptionKey));
Q3:如何处理大文件?
A:使用文件分块读写:
final file = File('large_file.bin');
final stream = file.openRead();
await for (var chunk in stream) {
// 处理每个块
}
最佳实践
1. 封装存储逻辑
// 错误:直接在 Widget 中使用
final prefs = await SharedPreferences.getInstance();
await prefs.setInt('counter', 42);
// 正确:封装到服务类
await PreferencesService.setCounter(42);
2. 使用异步操作
// 错误:同步阻塞
final value = prefs.getInt('key');
// 正确:异步处理
final value = await PreferencesService.getValue();
3. 处理异常
try {
await db.insert(user);
} catch (e) {
// 处理错误
}
总结
本地存储是 Flutter 应用的重要组成部分。通过本文的学习,你应该能够:
- 选择合适的存储方案
- 使用 SharedPreferences 存储简单数据
- 使用 Hive 存储复杂对象
- 使用 SQLite 存储关系型数据
- 实现数据持久化和恢复
掌握这些技巧,能够帮助你构建更加可靠的应用。
更多推荐
所有评论(0)