Flutter 结合 shared_preferences 2.5.4 实现本地轻量级数据存储

在日常 Flutter 开发中,经常会遇到需要存储用户偏好设置、登录状态、简单配置项等轻量级数据的场景。这类数据无需复杂的数据库结构,但要求读写高效、跨平台兼容且接入成本低。此前我尝试过手动封装原生存储逻辑(如 Android 的 SharedPreferences、iOS 的 NSUserDefaults),但存在代码冗余、多平台适配繁琐的问题。了解到 shared_preferences 是 Flutter 生态中专门解决这类问题的官方推荐插件,而 2.5.4 版本作为稳定版,不仅修复了旧版本的异步读写缺陷,还优化了多平台存储逻辑,因此专门深入学习该版本的使用方式,旨在掌握轻量级本地存储的标准化实现方案,提升项目中数据持久化的开发效率,同时规避因缓存、跨隔离区访问导致的数据一致性问题。

Flutter 结合 shared_preferences 2.5.4 实现本地轻量级数据存储

技术背景与需求分析

  • 移动应用数据持久化的常见场景
  • shared_preferences 的定位与适用场景(轻量级键值对存储)
  • 对比其他本地存储方案(SQLite、Hive、文件存储)

shared_preferences 2.5.4 核心特性

  • 支持数据类型:intdoubleboolStringList<String>
  • 跨平台兼容性(iOS/Android/Web)
  • 同步与异步操作差异说明

环境配置与依赖集成

  • pubspec.yaml 中添加依赖:

    yaml 复制代码
    dependencies:
      shared_preferences: ^2.5.4
  • 执行 flutter pub get

  • 导入库:

    dart 复制代码
    import 'package:shared_preferences/shared_preferences.dart';

基础操作实现

  • 初始化 SharedPreferences 实例:

    dart 复制代码
    final prefs = await SharedPreferences.getInstance();
  • 数据写入示例:

    dart 复制代码
    prefs.setInt('counter', 42);
    prefs.setString('username', 'FlutterUser');
  • 数据读取示例:

    dart 复制代码
    int? counter = prefs.getInt('counter');
    String? username = prefs.getString('username');
  • 删除数据与清空存储:

    dart 复制代码
    prefs.remove('counter');
    prefs.clear();

高级应用场景

  • 监听数据变化:通过 StreamValueNotifier 包装
  • 复杂对象存储:JSON 序列化与反序列化(结合 dart:convert
  • 安全增强:敏感数据加密建议(如结合 flutter_secure_storage

性能优化与最佳实践

  • 避免频繁调用 getInstance()
  • 批量写入使用 commit() 替代 set 方法链
  • 异常处理与空安全适配

常见问题排查

  • 数据类型不匹配导致的读取失败
  • Web 平台兼容性注意事项
  • 调试技巧:查看原生平台存储文件位置

实战案例演示

  • 用户偏好设置(主题、语言切换)
  • 应用状态持久化(登录状态、历史记录)
  • 离线缓存策略设计

版本迁移与升级指南

  • 从旧版本迁移到 2.5.4 的改动点
  • 废弃 API 替代方案

参考资料与扩展阅读

  • 官方插件文档链接
  • 社区推荐的最佳实践文章
  • 相关开源项目案例

一、shared_preferences 2.5.4 核心特性与适配说明

1.1 版本核心更新

特性 / 优化点 具体说明
API 稳定性提升 修复 2.3.x 版本中SharedPreferencesAsync异步读写的偶发阻塞问题
多平台适配完善 优化 Windows 端 AppData 目录读写权限,macOS 10.15 + 兼容性增强
缓存机制优化 SharedPreferencesWithCache的缓存刷新逻辑更高效,减少多隔离区数据不一致
迁移工具完善 提供更健壮的旧版 API 向新版异步 API 迁移工具,降低数据丢失风险

1.2 平台存储位置与支持类型

(1)各平台存储路径
平台 SharedPreferences(旧版) SharedPreferencesAsync/WithCache(新版)
Android 系统 SharedPreferences(xml 文件) DataStore Preferences(默认)/SharedPreferences
iOS/macOS NSUserDefaults NSUserDefaults
Linux XDG_DATA_HOME 目录下的键值文件 XDG_DATA_HOME 目录下的键值文件
Web 浏览器 LocalStorage 浏览器 LocalStorage
Windows 系统漫游 AppData 目录 系统漫游 AppData 目录
(2)支持的数据类型

该版本仅支持以下基础数据类型,不支持自定义对象(需序列化后以 String 存储):intdoubleboolStringList<String>

二、核心 API 分类与使用场景

2.5.4 版本提供三类核心 API,适配不同的开发场景,开发者可根据性能、数据一致性需求选择:

API 类型 核心特点 适用场景 性能 数据一致性
SharedPreferences(旧版) 带本地缓存,同步 get / 异步 set,未来将废弃 简单场景、低频次读写、无需跨隔离区访问 较低
SharedPreferencesAsync 无缓存,全异步读写,直接访问原生存储 多隔离区 / 多引擎实例、跨端数据同步场景
SharedPreferencesWithCache 带可控缓存,同步 get / 异步 set,可配置白名单 高频次读操作、需平衡性能与数据一致性场景

三、实操案例:不同 API 的使用方式

3.1 基础配置

首先在pubspec.yaml中引入依赖:

复制代码
dependencies:
  flutter:
    sdk: flutter
  shared_preferences: 2.5.4
  # 如需Android端指定SharedPreferences后端,需额外引入
  # shared_preferences_android: ^2.2.0

3.2 旧版 SharedPreferences(兼容使用)

适合快速实现简单存储,注意该 API 未来将废弃,新工程建议使用新版:

复制代码
import 'package:shared_preferences/shared_preferences.dart';

// 写入数据
Future<void> saveUserData() async {
  // 获取实例(异步)
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  // 写入不同类型数据
  await prefs.setInt('user_age', 25);
  await prefs.setBool('is_login', true);
  await prefs.setString('user_name', 'FlutterDev');
  await prefs.setStringList('hobbies', ['coding', 'reading', 'running']);
}

// 读取数据
Future<void> readUserData() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  // 同步读取,无数据返回null
  final int? age = prefs.getInt('user_age');
  final bool? isLogin = prefs.getBool('is_login');
  final String? name = prefs.getString('user_name');
  final List<String>? hobbies = prefs.getStringList('hobbies');
  
  print('用户名:$name,年龄:$age,是否登录:$isLogin');
}

// 删除数据
Future<void> removeData() async {
  final SharedPreferences prefs = await SharedPreferences.getInstance();
  await prefs.remove('user_age'); // 删除指定键
  // await prefs.clear(); // 清空所有数据
}

3.3 新版 SharedPreferencesAsync(推荐)

无缓存设计,保证数据一致性,适合多场景数据读写:

复制代码
import 'package:shared_preferences/shared_preferences.dart';

// 初始化异步实例
final SharedPreferencesAsync asyncPrefs = SharedPreferencesAsync();

// 写入数据
Future<void> saveDataAsync() async {
  await asyncPrefs.setDouble('score', 98.5);
  await asyncPrefs.setString('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');
}

// 读取数据
Future<void> readDataAsync() async {
  final double? score = await asyncPrefs.getDouble('score');
  final String? token = await asyncPrefs.getString('token');
  print('分数:$score,Token:$token');
}

// 清空数据(指定白名单,仅删除白名单外数据)
Future<void> clearDataAsync() async {
  await asyncPrefs.clear(allowList: {'token'}); // 保留token键
}

3.4 SharedPreferencesWithCache(高性能读写)

带缓存的新版 API,适合高频读场景,可配置白名单限制可操作的键:

复制代码
import 'package:shared_preferences/shared_preferences.dart';

// 创建带缓存的实例,指定白名单
Future<void> initCachePrefs() async {
  final SharedPreferencesWithCache prefsWithCache = await SharedPreferencesWithCache.create(
    cacheOptions: const SharedPreferencesWithCacheOptions(
      allowList: {'theme_mode', 'font_size'}, // 仅允许操作这两个键
    ),
  );
  
  // 写入数据
  await prefsWithCache.setInt('font_size', 16);
  await prefsWithCache.setBool('theme_mode', true);
  
  // 同步读取缓存数据
  final int? fontSize = prefsWithCache.getInt('font_size');
  print('字体大小:$fontSize');
  
  // 清空数据(白名单已配置,无需重复传)
  await prefsWithCache.clear();
}

3.5 旧版迁移到新版 API

2.5.4 版本提供了便捷的迁移工具,确保旧版数据无缝迁移到新版异步 API:

复制代码
import 'package:shared_preferences/shared_preferences.dart';
import 'package:shared_preferences/util/legacy_to_async_migration_util.dart';

Future<void> migrateData() async {
  // 获取旧版实例
  final SharedPreferences legacyPrefs = await SharedPreferences.getInstance();
  // 执行迁移(仅首次执行,通过migrationCompletedKey标记)
  await migrateLegacySharedPreferencesToSharedPreferencesAsyncIfNecessary(
    legacySharedPreferencesInstance: legacyPrefs,
    sharedPreferencesAsyncOptions: const SharedPreferencesOptions(),
    migrationCompletedKey: 'migration_completed_2025', // 自定义标记键
  );
}

四、注意事项

  1. 数据安全性:该插件仅适用于非敏感数据存储(如用户偏好设置、简单配置),密码、token 等敏感数据需加密后再存储;
  2. 跨隔离区使用 :若在多隔离区中使用带缓存的 API,需在读取前调用reload()刷新缓存,避免数据不一致;
  3. Android 后端选择 :如需兼容原生 Android 的 SharedPreferences 数据,需通过SharedPreferencesAsyncAndroidOptions指定后端类型;
  4. 数据量限制:适合存储 KB 级别的小数据,大量数据建议使用 Hive、SQFlite 等数据库。

五、总结

shared_preferences 2.5.4 版本通过三类差异化 API,满足了 Flutter 开发者在不同场景下的本地轻量级存储需求。新版异步 API(SharedPreferencesAsync/WithCache)解决了旧版缓存导致的数据一致性问题,同时保持了易用性;旧版 API 则可作为过渡方案。开发者可根据项目的性能、一致性需求选择合适的 API,结合平台特性做好适配,高效实现本地数据持久化。

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。

相关推荐
走在路上的菜鸟5 小时前
Android学Dart学习笔记第十六节 类-构造方法
android·笔记·学习·flutter
hh.h.9 小时前
Flutter适配鸿蒙轻量设备的资源节流方案
flutter·华为·harmonyos
巴拉巴拉~~9 小时前
Flutter 通用下拉刷新上拉加载列表 RefreshListWidget:分页 + 空态 + 错误处理
flutter
走在路上的菜鸟9 小时前
Android学Dart学习笔记第十七节 类-成员方法
android·笔记·学习·flutter
走在路上的菜鸟10 小时前
Android学Dart学习笔记第十八节 类-继承
android·笔记·学习·flutter
巴拉巴拉~~10 小时前
Flutter 通用列表刷新加载组件 CommonRefreshList:下拉刷新 + 上拉加载 + 状态适配
前端·javascript·flutter
走在路上的菜鸟10 小时前
Android学Dart学习笔记第十九节 类-混入Mixins
android·笔记·学习·flutter
ujainu小10 小时前
Flutter file_selector 插件:跨平台文件交互完全指南
flutter
爱吃大芒果11 小时前
Flutter 列表优化:ListView 性能调优与复杂列表实现
开发语言·hive·hadoop·flutter·华为