Flutter SharedPreferences 本地存储详解
Flutter SharedPreferences 本地存储详解
一、SharedPreferences 概述
SharedPreferences 是一种轻量级的本地存储方案,用于存储键值对数据。它适用于存储少量配置信息、用户偏好设置等简单数据。
1.1 特点
- 轻量级,适合存储少量数据
- 基于 XML 文件存储
- 支持基本数据类型:int、double、bool、String、List
- 数据持久化存储
1.2 添加依赖
dependencies: shared_preferences: ^2.2.2二、基本用法
2.1 初始化
import 'package:shared_preferences/shared_preferences.dart'; Future<void> initPrefs() async { final prefs = await SharedPreferences.getInstance(); // 使用 prefs 进行存储操作 }2.2 存储数据
final prefs = await SharedPreferences.getInstance(); // 存储字符串 await prefs.setString('username', 'John'); // 存储整数 await prefs.setInt('age', 25); // 存储布尔值 await prefs.setBool('isDarkMode', true); // 存储浮点数 await prefs.setDouble('score', 95.5); // 存储字符串列表 await prefs.setStringList('favoriteColors', ['red', 'blue', 'green']);2.3 读取数据
final prefs = await SharedPreferences.getInstance(); // 读取字符串,默认值为 '' String? username = prefs.getString('username'); // 读取整数,默认值为 0 int age = prefs.getInt('age') ?? 0; // 读取布尔值,默认值为 false bool isDarkMode = prefs.getBool('isDarkMode') ?? false; // 读取浮点数,默认值为 0.0 double score = prefs.getDouble('score') ?? 0.0; // 读取字符串列表,默认值为空列表 List<String> favoriteColors = prefs.getStringList('favoriteColors') ?? [];2.4 删除数据
final prefs = await SharedPreferences.getInstance(); // 删除单个键 await prefs.remove('username'); // 清除所有数据 await prefs.clear();2.5 检查键是否存在
final prefs = await SharedPreferences.getInstance(); bool hasUsername = prefs.containsKey('username');三、封装工具类
3.1 创建存储服务
import 'package:shared_preferences/shared_preferences.dart'; class StorageService { static late SharedPreferences _prefs; static Future<void> init() async { _prefs = await SharedPreferences.getInstance(); } static String? getString(String key) { return _prefs.getString(key); } static Future<bool> setString(String key, String value) { return _prefs.setString(key, value); } static int? getInt(String key) { return _prefs.getInt(key); } static Future<bool> setInt(String key, int value) { return _prefs.setInt(key, value); } static bool? getBool(String key) { return _prefs.getBool(key); } static Future<bool> setBool(String key, bool value) { return _prefs.setBool(key, value); } static double? getDouble(String key) { return _prefs.getDouble(key); } static Future<bool> setDouble(String key, double value) { return _prefs.setDouble(key, value); } static List<String>? getStringList(String key) { return _prefs.getStringList(key); } static Future<bool> setStringList(String key, List<String> value) { return _prefs.setStringList(key, value); } static bool containsKey(String key) { return _prefs.containsKey(key); } static Future<bool> remove(String key) { return _prefs.remove(key); } static Future<bool> clear() { return _prefs.clear(); } }3.2 在 main 函数中初始化
void main() async { WidgetsFlutterBinding.ensureInitialized(); await StorageService.init(); runApp(const MyApp()); }四、实战案例:用户设置管理
4.1 创建设置模型
class UserSettings { final String themeMode; final String language; final bool notificationsEnabled; final int fontSize; const UserSettings({ required this.themeMode, required this.language, required this.notificationsEnabled, required this.fontSize, }); // 从存储读取 static UserSettings fromStorage() { return UserSettings( themeMode: StorageService.getString('themeMode') ?? 'light', language: StorageService.getString('language') ?? 'zh', notificationsEnabled: StorageService.getBool('notificationsEnabled') ?? true, fontSize: StorageService.getInt('fontSize') ?? 16, ); } // 保存到存储 Future<void> save() async { await StorageService.setString('themeMode', themeMode); await StorageService.setString('language', language); await StorageService.setBool('notificationsEnabled', notificationsEnabled); await StorageService.setInt('fontSize', fontSize); } }4.2 使用设置模型
class SettingsPage extends StatelessWidget { const SettingsPage({super.key}); @override Widget build(BuildContext context) { final settings = UserSettings.fromStorage(); return Scaffold( appBar: AppBar(title: const Text('设置')), body: ListView( children: [ ListTile( title: const Text('主题模式'), subtitle: Text(settings.themeMode), onTap: () async { final newSettings = UserSettings( themeMode: 'dark', language: settings.language, notificationsEnabled: settings.notificationsEnabled, fontSize: settings.fontSize, ); await newSettings.save(); }, ), // 更多设置项... ], ), ); } }五、高级用法
5.1 存储复杂对象
虽然 SharedPreferences 只支持基本类型,但可以通过 JSON 序列化存储复杂对象:
import 'dart:convert'; class User { final String id; final String name; final int age; User({required this.id, required this.name, required this.age}); Map<String, dynamic> toJson() { return { 'id': id, 'name': name, 'age': age, }; } factory User.fromJson(Map<String, dynamic> json) { return User( id: json['id'], name: json['name'], age: json['age'], ); } } // 存储 final user = User(id: '1', name: 'John', age: 25); final userJson = jsonEncode(user.toJson()); await StorageService.setString('user', userJson); // 读取 final userJson = StorageService.getString('user'); if (userJson != null) { final user = User.fromJson(jsonDecode(userJson)); }5.2 监听数据变化
class SettingsProvider extends ChangeNotifier { UserSettings _settings = UserSettings.fromStorage(); UserSettings get settings => _settings; Future<void> updateThemeMode(String themeMode) async { _settings = UserSettings( themeMode: themeMode, language: _settings.language, notificationsEnabled: _settings.notificationsEnabled, fontSize: _settings.fontSize, ); await _settings.save(); notifyListeners(); } }六、注意事项
6.1 数据类型限制
SharedPreferences 只支持以下数据类型:
intdoubleboolStringList<String>
6.2 数据大小限制
建议存储的数据不超过 1MB,大量数据应使用数据库(如 Hive、SQFlite)。
6.3 异步操作
所有写入操作都是异步的,需要使用await等待完成。
6.4 数据清理
卸载应用时,SharedPreferences 数据会被清除。
七、与其他存储方案对比
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| SharedPreferences | 配置信息、用户偏好 | 轻量级、使用简单 | 数据类型有限、容量小 |
| Hive | 中等数据量、复杂对象 | 支持自定义对象、速度快 | 需要学习成本 |
| SQFlite | 大量数据、复杂查询 | 支持 SQL、数据量大 | 使用复杂、学习成本高 |
| File | 文件存储 | 灵活、适合二进制数据 | 需要手动管理 |
八、实战案例:登录状态管理
class AuthService { static const String _keyIsLoggedIn = 'isLoggedIn'; static const String _keyUserId = 'userId'; static const String _keyToken = 'token'; static Future<bool> isLoggedIn() async { final prefs = await SharedPreferences.getInstance(); return prefs.getBool(_keyIsLoggedIn) ?? false; } static Future<void> login(String userId, String token) async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(_keyIsLoggedIn, true); await prefs.setString(_keyUserId, userId); await prefs.setString(_keyToken, token); } static Future<void> logout() async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool(_keyIsLoggedIn, false); await prefs.remove(_keyUserId); await prefs.remove(_keyToken); } static Future<String?> getToken() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString(_keyToken); } }九、测试
9.1 单元测试
import 'package:shared_preferences/shared_preferences.dart'; import 'package:test/test.dart'; void main() { group('StorageService', () { late SharedPreferences prefs; setUp(() async { prefs = await SharedPreferences.getInstance(); await prefs.clear(); }); test('set and get string', () async { await prefs.setString('key', 'value'); expect(prefs.getString('key'), 'value'); }); test('set and get int', () async { await prefs.setInt('count', 42); expect(prefs.getInt('count'), 42); }); test('remove key', () async { await prefs.setString('key', 'value'); expect(prefs.containsKey('key'), true); await prefs.remove('key'); expect(prefs.containsKey('key'), false); }); }); }十、总结
SharedPreferences 是 Flutter 中最简单的本地存储方案:
- 适用场景- 存储配置信息、用户偏好设置、简单状态
- 优点- 使用简单、轻量级、异步操作
- 局限性- 数据类型有限、容量较小
- 最佳实践- 封装成工具类、配合 Provider 管理状态
对于更复杂的存储需求,可以考虑 Hive 或 SQFlite。
