用 shared_preferences 持久化偏好设置和轻量数据,同时了解它在安全性和容量上的局限。
在 Kodokon 中打开本课shared_preferences 是一个键/值存储,背后依托的是原生机制(Android 上的 SharedPreferences、iOS 上的 UserDefaults)。它的最佳场景是:小块数据 - 选定的主题、是否看过引导页、上次激活的标签页。超出这个范围就该换工具了:大块或需要查询的数据用 sqflite 或 drift 数据库,任何敏感的东西用 flutter_secure_storage。这个文件会被整个加载进内存:它既没有加密,也不是为增长而设计的。
flutter pub add shared_preferencesgetInstance() 在第一次调用时是异步的(要读取文件),之后会返回一个被缓存的实例:随后的 get* 调用是同步的,直接从内存中取值。而 set* 调用则会异步地写入磁盘。在实践中,不要把键的字符串散落在整个应用各处:把它们集中到一个类型化的、可注入的、可测试的封装里。
import 'package:shared_preferences/shared_preferences.dart';
class SettingsStore {
SettingsStore(this._prefs);
static const _darkModeKey = 'settings.darkMode';
final SharedPreferences _prefs;
static Future<SettingsStore> load() async {
final prefs = await SharedPreferences.getInstance();
return SettingsStore(prefs);
}
bool get darkMode =>
_prefs.getBool(_darkModeKey) ?? false;
Future<void> setDarkMode(bool value) =>
_prefs.setBool(_darkModeKey, value);
}这个 API 只存储原始类型:bool、int、double、String 以及 List<String>。对于一个结构化对象,请把它序列化成 JSON - 你在第一课里写的 toJson/fromJson 在这里又能派上用场了。一个可以接受的取舍是:每次保存都会重写整个值,而且无法进行查询。它非常适合保存一份草稿,却不适合保存一段历史记录。
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class Draft {
const Draft({required this.title, required this.body});
factory Draft.fromJson(Map<String, dynamic> json) =>
Draft(
title: json['title'] as String,
body: json['body'] as String,
);
final String title;
final String body;
Map<String, dynamic> toJson() =>
{'title': title, 'body': body};
}
Future<void> saveDraft(Draft draft) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('draft', jsonEncode(draft));
}
Future<Draft?> loadDraft() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString('draft');
if (raw == null) return null;
return Draft.fromJson(
jsonDecode(raw) as Map<String, dynamic>,
);
}shared_preferences?getInstance() 之后,get* 读取操作的表现如何?Future,每次都必须 await。Draft 对象?jsonEncode 把它序列化成 JSON,再通过 setString 存储。prefs.setObject('draft', draft)。setStringList。