当前位置: 首页 > 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.gsyq.cn/news/1410715.html

相关文章:

  • 期刊论文写作心得:巧用辅助工具,解锁学术撰文的高效之道
  • 【ChatGPT商业竞争格局解码】:用波特五力模型穿透AI大模型赛道的护城河与生死线
  • 从被动执行到主动驱动:如何构建自我驱动的思维与行动框架
  • MathType装完Word里不显示?可能是Office的‘信任中心’在搞鬼,5分钟教你设置好
  • OpenAPI x-agent-trust扩展:为AI智能体构建API信任机制
  • Keil C51内存重叠警告(L5)解析与解决方案
  • MySQL排序规则(Collation)详解:从一次SQL注入报错讲起,如何避免和排查字符集问题
  • STM32CubeMX外部中断配置避坑指南:从引脚模式到回调函数,新手常犯的5个错误
  • 使用 Taotoken CLI 工具一键配置多开发环境下的 API 访问密钥
  • 蓝桥杯单片机DS18B20温度测量:从数据手册到四位小数显示的完整代码解析(含负数处理)
  • 2026年 雨水井模具/污水井模具/阀门井模具/电信井模具/电缆井模具/圆井模具/检查井模具/方井模具/拼装方井模具厂家推荐:质量过硬与工艺精度口碑之选 - 品牌企业推荐师(官方)
  • RTX51与C51版本兼容性问题解析与解决方案
  • SARscape实战:手把手教你处理.hgt格式SRTM DEM,解决干涉处理报错难题
  • 智能体架构设计:MCP与A2A协议的分层协作与选型指南
  • 基于硬件在环的并联逆变器系统实时稳定性分析与在线监测
  • 告别有线烧录:手把手教你用MQTT+HTTP为STM32设备打造无线OTA升级系统(附状态机源码)
  • Agiwo框架:从工具调用到工作流编排的AI应用架构设计
  • Mac本地语音AI助手:基于Ollama与3-Model Chain的完整实现
  • 200行代码实现RevenueCat订阅数据自动化报告与可视化
  • 别再硬编码了!用UE4/UE5的GameplayTag动态管理你的技能触发逻辑
  • FPGA固化程序到Flash踩坑记:从Vivado警告[Labtools 27-2251]到硬件原理图复盘
  • 基于Hindsight构建有记忆的客服AI:告别健忘,实现连续对话体验
  • 通过OpenClaw配置Taotoken实现自动化智能体工作流
  • 使用Terraform实现Amazon SageMaker模型端点的自动化部署与管理
  • 多智能体强化学习在水下机器人珊瑚采样中的应用
  • 如何用象棋AI辅助工具在3分钟内获得大师级棋局分析
  • GPT-6发布在即:开发者如何应对API成本冲击与智能模型路由策略
  • 别再死记硬背HTML标签了!用Educoder实训项目手把手教你搭建第一个网页(附完整代码)
  • 2026年评价高的常熟单面硅胶布/半生半熟硅胶布/防火阻燃硅胶布/常熟防火密封硅胶布优质公司推荐 - 行业平台推荐
  • AI数据处理中ANSI颜色码的隐藏成本与清洗实战