当前位置: 首页 > news >正文

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 只支持以下数据类型:

  • int
  • double
  • bool
  • String
  • List<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 中最简单的本地存储方案:

  1. 适用场景- 存储配置信息、用户偏好设置、简单状态
  2. 优点- 使用简单、轻量级、异步操作
  3. 局限性- 数据类型有限、容量较小
  4. 最佳实践- 封装成工具类、配合 Provider 管理状态

对于更复杂的存储需求,可以考虑 Hive 或 SQFlite。

http://www.jsqmd.com/news/901335/

相关文章:

  • 网络的分类(按规模):从你身边到全世界的网络大冒险
  • 2026年热门的断桥铝门窗阳光房定制/泰安高端断桥铝门窗/断桥铝门窗系统窗多家厂家对比分析 - 品牌宣传支持者
  • Lancet Digit Health(IF=24.1)牛津大学:基于Transformer的心血管病预防性治疗人群筛选
  • ChatGPT五力衰退预警信号已出现!3个关键指标异动(附企业级应对SOP清单)
  • 每周演示可工作软件:弥合团队鸿沟、重塑敏捷交付的核心实践
  • 2026年 钢材质保书/产品质量证明书推荐榜:覆盖宝钢/宝武钢/首钢/鞍钢/山钢/武钢,钢厂直供正品保障! - 品牌企业推荐师(官方)
  • Lancet Digital Health(IF=24.1)德国德累斯顿工业大学医学院:深度学习评估结直肠癌的基因型-表型相关性
  • 2026年靠谱的盐城激光耐高温加工/激光加工/激光局部淬火加工/齿轮激光表面修复加工厂家选择推荐 - 行业平台推荐
  • ALFI:CPU-GPU异构并行架构在潜指纹识别中的极致性能优化实践
  • 速腾聚创RS-M1激光雷达开箱实测:从拆箱到上电,手把手教你避坑布线
  • MySQL/PostgreSQL实战:你的表设计真的规范吗?手把手教你用SQL语句检测范式违反
  • FreeRTOS的configMAX_SYSCALL_INTERRUPT_PRIORITY:你的API安全调用边界设对了吗?
  • Windows 11/10下CUDA 12.1与PyTorch 2.0+的黄金搭档:手把手教你搭建能跑模型的GPU环境
  • Mac本地语音AI助手:基于Ollama与3-Model Chain的完整实现
  • 量子退火求解双目标旅行小偷问题:ε约束法与QUBO建模实践
  • Sci. Adv.(IF=12.5)首都医科大学宣武医院卢洁等团队:一种用于预测乳腺癌新辅助化疗病理完全缓解的多模态全自动系统
  • 怎么用投票小程序创建微信投票(云帆投票三步搞定) - 投票小程序
  • Cortex-M3字节序机制与优化实践
  • Unity游戏开发实战:手把手教你用C#复刻Townscaper的有机网格生成(附完整源码)
  • MathType装完Word里不显示?可能是Office的‘信任中心’在搞鬼,5分钟教你设置好
  • 告别PyCharm红色波浪线:快速修复第三方库识别失败的3种实用方法(含Pythonw.exe选择指南)
  • OpenAPI x-agent-trust扩展:为AI智能体构建API信任机制
  • 2026年质量好的自贡非遗传统花灯/LED花灯/户外花灯/国潮花灯实力工厂推荐 - 品牌宣传支持者
  • MySQL排序规则(Collation)详解:从一次SQL注入报错讲起,如何避免和排查字符集问题
  • Agiwo框架:从工具调用到工作流编排的AI应用架构设计
  • 别再瞎调了!ACfly飞控ADRC参数整定保姆级指南(附Simulink仿真避坑)
  • STM32CubeMX外部中断配置避坑指南:从引脚模式到回调函数,新手常犯的5个错误
  • 从手动整理到智能检索:我用AI工具管理素材库的实践
  • 从庞贝到元宇宙:如何用Blender和Unreal Engine 5重建一座2000年前的古城
  • Nolex:基于本地正则与AI检测的浏览器插件,守护AI交互中的敏感数据安全