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)