12_本地存储
Flutter 本地数据存储方案
SharedPreferences(轻量键值)、SQLite(结构化数据)、文件存储。
三种方案对比
| 方案 | 类比 Web | 适用场景 |
|---|---|---|
| SharedPreferences | localStorage |
简单配置、Token、用户偏好 |
| SQLite(sqflite) | IndexedDB | 复杂结构化数据、离线数据库 |
| 文件存储 | File System API | 大文件、图片、日志 |
SharedPreferences
dependencies:
shared_preferences: ^2.2.0
import 'package:shared_preferences/shared_preferences.dart';
class PrefsService {
static SharedPreferences? _prefs;
// 初始化(在 main() 中调用一次)
static Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
}
// 写入
static Future<void> setString(String key, String value) =>
_prefs!.setString(key, value);
static Future<void> setBool(String key, bool value) =>
_prefs!.setBool(key, value);
static Future<void> setInt(String key, int value) =>
_prefs!.setInt(key, value);
static Future<void> setStringList(String key, List<String> value) =>
_prefs!.setStringList(key, value);
// 读取(带默认值)
static String getString(String key, {String defaultValue = ''}) =>
_prefs!.getString(key) ?? defaultValue;
static bool getBool(String key, {bool defaultValue = false}) =>
_prefs!.getBool(key) ?? defaultValue;
static int getInt(String key, {int defaultValue = 0}) =>
_prefs!.getInt(key) ?? defaultValue;
// 删除 / 清空
static Future<void> remove(String key) => _prefs!.remove(key);
static Future<void> clear() => _prefs!.clear();
static bool hasKey(String key) => _prefs!.containsKey(key);
}
// main.dart 中初始化
void main() async {
WidgetsFlutterBinding.ensureInitialized(); // 异步初始化前必须调用
await PrefsService.init();
runApp(const MyApp());
}
// 使用
await PrefsService.setString('auth_token', token);
final token = PrefsService.getString('auth_token');
await PrefsService.setBool('is_dark_mode', true);
final isDark = PrefsService.getBool('is_dark_mode');
SQLite(sqflite)
dependencies:
sqflite: ^2.3.0
path: ^1.8.0
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class DatabaseHelper {
static Database? _db;
static Future<Database> get db async {
_db ??= await _init();
return _db!;
}
static Future<Database> _init() async {
final path = join(await getDatabasesPath(), 'app.db');
return openDatabase(
path,
version: 2,
onCreate: (db, version) async {
await db.execute('''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
age INTEGER DEFAULT 0,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
''');
},
onUpgrade: (db, oldVersion, newVersion) async {
// 数据库版本升级(类似 migration)
if (oldVersion < 2) {
await db.execute('ALTER TABLE users ADD COLUMN avatar TEXT');
}
},
);
}
// ── CRUD ────────────────────────────────
// 插入(返回新行的 id)
static Future<int> insertUser(Map<String, dynamic> user) async {
final database = await db;
return database.insert(
'users',
user,
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
// 查询全部
static Future<List<Map<String, dynamic>>> getUsers() async {
final database = await db;
return database.query('users', orderBy: 'created_at DESC');
}
// 条件查询
static Future<Map<String, dynamic>?> getUserById(int id) async {
final database = await db;
final rows = await database.query(
'users',
where: 'id = ?',
whereArgs: [id],
limit: 1,
);
return rows.isEmpty ? null : rows.first;
}
// 模糊搜索
static Future<List<Map<String, dynamic>>> searchUsers(String keyword) async {
final database = await db;
return database.query(
'users',
where: 'name LIKE ? OR email LIKE ?',
whereArgs: ['%$keyword%', '%$keyword%'],
);
}
// 更新
static Future<int> updateUser(int id, Map<String, dynamic> data) async {
final database = await db;
return database.update('users', data, where: 'id = ?', whereArgs: [id]);
}
// 删除
static Future<int> deleteUser(int id) async {
final database = await db;
return database.delete('users', where: 'id = ?', whereArgs: [id]);
}
// 原始 SQL
static Future<List<Map<String, dynamic>>> rawQuery(String sql, [List? args]) async {
final database = await db;
return database.rawQuery(sql, args);
}
}
// 使用示例
final id = await DatabaseHelper.insertUser({
'name': 'Alice',
'email': 'alice@example.com',
'age': 25,
});
final users = await DatabaseHelper.getUsers();
for (final user in users) {
print('${user['id']}: ${user['name']}');
}
文件存储
dependencies:
path_provider: ^2.1.0
import 'dart:io';
import 'dart:convert';
import 'package:path_provider/path_provider.dart';
class FileService {
// 应用私有文档目录(用户不可见,卸载时清除)
static Future<Directory> get _docDir =>
getApplicationDocumentsDirectory();
// 临时缓存目录(系统可能自动清理)
static Future<Directory> get _cacheDir =>
getTemporaryDirectory();
// 写入文本
static Future<void> writeText(String filename, String content) async {
final dir = await _docDir;
await File('${dir.path}/$filename').writeAsString(content);
}
// 读取文本
static Future<String> readText(String filename) async {
final dir = await _docDir;
final file = File('${dir.path}/$filename');
if (!await file.exists()) return '';
return file.readAsString();
}
// 写入 JSON
static Future<void> writeJson(String filename, dynamic data) async {
await writeText(filename, jsonEncode(data));
}
// 读取 JSON
static Future<dynamic> readJson(String filename) async {
final text = await readText(filename);
if (text.isEmpty) return null;
return jsonDecode(text);
}
// 检查文件是否存在
static Future<bool> exists(String filename) async {
final dir = await _docDir;
return File('${dir.path}/$filename').exists();
}
// 删除文件
static Future<void> delete(String filename) async {
final dir = await _docDir;
final file = File('${dir.path}/$filename');
if (await file.exists()) await file.delete();
}
// 列出所有文件
static Future<List<String>> listFiles() async {
final dir = await _docDir;
final files = dir.listSync();
return files.map((f) => f.path.split('/').last).toList();
}
}
// 使用
await FileService.writeJson('user_cache.json', {'name': 'Alice', 'age': 25});
final data = await FileService.readJson('user_cache.json');