
shared_preferences_web 版本演进全解析Web 端 LocalStorage 持久化插件的迭代路线与技术实现【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages本文以shared_preferences_webFlutter 官方shared_preferences联邦插件体系的 Web 端实现的 CHANGELOG.md 为主线梳理该包从 0.1.0 初始发布到 2.4.3 的全部版本迭代脉络并结合仓库源码深入讲解其核心 APISharedPreferencesPlugin与SharedPreferencesAsyncWeb、LocalStorage 存储机制、JSON 编解码与容错策略、prefix/allowList 过滤模型以及集成测试的组织方式。读完本文你将能够准确判断各版本的能力边界、理解 Web 端偏好存储的底层行为并掌握在 Flutter Web 工程中正确接入与验证该插件的方法。一、包定位联邦插件中的 Web 平台实现shared_preferences_web是 Flutter 官方插件仓库中shared_preferences的 Web 平台实现其 pubspec 描述为 Web platform implementation of shared_preferences版本号为 2.4.3。它属于 Flutter 官方的联邦插件federated plugin体系对外暴露统一 API 的是shared_preferences主包各平台由独立的实现包负责Web 端即由本包承接最终落在浏览器的 LocalStorage 上主包 README 的存储位置对照表明确列出 Web → LocalStorage。从 pubspec.yaml 可以确认本包是**被背书endorsed**的平台实现flutter: plugin: implements: shared_preferences platforms: web: pluginClass: SharedPreferencesPlugin fileName: shared_preferences_web.dartimplements: shared_preferences表示应用只要在pubspec.yaml中声明依赖shared_preferencesFlutter 工具链就会自动把本包作为 Web 端实现带入工程无需手动添加本包依赖详见本包 README 的 Usage 说明。唯一的例外是当你需要直接import本包以使用其独有 API例如SharedPreferencesAsyncWeb或SharedPreferencesWebOptions时才需要把shared_preferences_web显式加入依赖。该包当前依赖shared_preferences_platform_interface: ^2.4.0与web: 0.5.1 2.0.0并声明了persistence、shared-preferences、storage三个 pub topics 便于检索。二、版本迭代主线从 0.1.0 到 2.4.3 的四个阶段CHANGELOG 完整记录了该包自 2019 年前后的 0.1.0 初始发布至 2.4.3 的全部演进可以归纳为四个阶段。阶段一0.1.x 起步期联邦插件初建0.1.0 / 0.1.01Initial release移除 pubspec 中已废弃的author:字段要求 Flutter SDK 1.10.0。0.1.1新增shared_preferences_macos包联邦拆分的一部分。0.1.2 系列补充 stub podspec 文件为规避 flutter/flutter#46898 添加了无实际操作的 android/ 目录0.1.21随后在 0.1.27 中移除该目录0.1.23 提升 gradle 版本以避免 Android 工程问题——这些都是联邦插件早期跨平台兼容性的修补痕迹。0.1.25声明 API 稳定性并兼容 1.0.0是包进入稳定版前的关键信号。阶段二2.0.x 空安全与工程规范化2021 年前后2.0.0Migrate to null-safety这是 Dart 2.12 空安全普及期的核心迁移随后所有 API 均采用可空返回类型如Futureint?。2.0.1更新 README 安装说明并把测试迁移到example目录下使其作为flutter drive驱动的集成测试运行——这一决策直接奠定了本包今日的测试组织形态。2.0.2在 pubspec 中补充implements字段正式明确联邦背书关系。2.0.3移除对meta包的依赖修复新启用的 analyzer 选项。2.0.4修复library_private_types_in_public_api、sort_child_properties_last、use_key_in_widget_constructors等 lint 警告。2.0.5 / 2.0.6更新为 flutter/plugins 并入 flutter/packages 后的链接最低 Flutter 版本升至 3.0并对齐 Dart/Flutter SDK 约束、澄清 README 中关于背书机制的解释。阶段三2.1.x – 2.3.0 功能扩展期2.1.0新增getAllWithPrefix与clearWithPrefix方法——为按前缀批量读取/清理数据提供了官方入口。2.2.0进一步新增clearWithParameters与getAllWithParameters方法引入了更通用的ClearParameters/GetAllParameters参数对象并在其内部支持PreferencesFilter可携带 prefix 与 allowList把过滤能力从仅前缀升级为前缀 白名单。2.2.1为包元数据补充 pub topics最低 SDK 提升至 Flutter 3.7/Dart 2.19。2.2.2最低 Dart SDK 提升至 3.2。2.3.0Web 代码从package:js/dart:html时代升级为web: ^0.5.0CHANGELOG 中 Updates web code to package web 即指此迁移SDK 约束提升至 Dart ^3.3.0 / Flutter ^3.19.0。阶段四2.4.x 新异步 API 与健壮性修复期2.4.0新增SharedPreferencesAsyncWebAPI对应平台接口层新增的SharedPreferencesAsyncPlatform为使用SharedPreferencesAsync的 Web 应用提供无缓存、直接读写 LocalStorage 的异步实现。2.4.1支持web: ^1.0.0web包 1.x 正式版。2.4.2修复getStringList返回不可变列表的问题最低 SDK 升至 Flutter 3.22/Dart 3.4。2.4.3修复非 JSON 格式字符串导致解析错误的问题——即对 LocalStorage 中由其他代码写入的非 JSON 值做到安全跳过而不是抛错。NEXT未发布最低 SDK 版本将更新至 Flutter 3.38/Dart 3.10与当前仓库 pubspec 中sdk: ^3.10.0、flutter: 3.38.0一致。三、核心实现源码解析3.1 存储介质与命名约定flutter.前缀Web 端所有数据都存于html.window.localStorage浏览器 LocalStorage。与移动端类似本包保留了默认前缀约定SharedPreferencesPlugin中定义了static const String _defaultPrefix flutter.见 shared_preferences_web.dart。这意味着主包SharedPreferences写入的键实际形如flutter.counter而clear()、getAll()等无参方法默认只作用于flutter.前缀之内的键。用户通过SharedPreferences.setPrefix修改前缀后所有操作会携带新的前缀下发到平台层。3.2 传统 APISharedPreferencesPluginSharedPreferencesPlugin extends SharedPreferencesStorePlatform其registerWith负责注册两套实现static void registerWith(Registrar? registrar) { SharedPreferencesStorePlatform.instance SharedPreferencesPlugin(); SharedPreferencesAsyncWeb.registerWith(registrar); }平台层方法的实现非常直白全部是对localStorage的同步 API 包装setValue→localStorage.setItem(key, _encodeValue(value))remove→localStorage.removeItem(key)getAll/getAllWithParameters→ 遍历_getPrefixedKeys命中的键逐一getItem并_decodeValueclear/clearWithParameters→ 仅删除命中前缀及可选 allowList的键。值得特别注意的是源码中的醒目注释shared_preferences_web.dart// IMPORTANT: Do not use html.window.localStorage.clear() as that will // remove _all_ local data, not just the keys prefixed with // _prefix _getPrefixedKeys(filter.prefix, allowList: filter.allowList).forEach(remove);即clear()的实现刻意不使用localStorage.clear()因为那会清掉同源下所有应用/其他库写入的 LocalStorage 数据而本包只应清理自己前缀范围内的键。这是 Web 实现与隔离性直接相关的关键设计决策。键枚举依赖KeysExtension见 keys_extension.dart它给html.Storage增加了一个keysgetter把length/key(i)包装成ListString供前缀过滤遍历使用。3.3 新异步 APISharedPreferencesAsyncWeb自 2.4.0 引入的base class SharedPreferencesAsyncWeb extends SharedPreferencesAsyncPlatform面向新版SharedPreferencesAsyncAPI。与缓存型 API 不同它不维护本地缓存每次 get 都直接回源读取 LocalStorage从而能拿到最新数据代价是每次调用都是异步 I/O。setString/setBool/setDouble/setInt/setStringList→ 统一走_setValue→localStorage.setItemgetString/getBool/.../getStringList→ 调用_readAllFromLocalStorage(String{key}, options)即通过 allowList 精确限定只读取目标键getPreferences→_readAllFromLocalStorage(filter.allowList, options)getKeys→ 返回getPreferences(...).keys.toSet()clear→ 按 filter 删除键。该实现还定义了 Web 专属的SharedPreferencesWebOptions extends SharedPreferencesOptions空实现占位表示Web 平台目前无需额外选项供SharedPreferencesAsync在 Web 端传入 options 使用。3.4 JSON 编解码与容错2.4.3 修复的根源Web 端把 Dart 值编码为 JSON 字符串后写入 LocalStorage。顶层函数_encodeValue/_decodeValueshared_preferences_web.dart是 2.4.2 与 2.4.3 两个修复的核心String _encodeValue(Object? value) { return json.encode(value); } Object? _decodeValue(String encodedValue) { final Object? decodedValue; try { decodedValue json.decode(encodedValue); } on FormatException catch (_) { return null; // 2.4.3非 JSON 字符串直接视为无效值返回 null 而非抛错 } if (decodedValue is List) { // JSON 不保留泛型信息ListString JSON Listdynamic // 必须显式恢复 RTTI。 return decodedValue.castString(); } return decodedValue; }两个版本修复对应两层问题2.4.2 的getStringList不可变列表修复_decodeValue已显式castString恢复泛型而getStringList返回时再调用.toList()见 shared_preferences_web.dart确保调用方拿到的是可变列表可以安全地增删元素。2.4.3 的非 JSON 容错修复若 LocalStorage 中某个键的值是其他代码写入的裸字符串如value而非\value\json.decode会抛FormatException。2.4.3 之前该异常会向上传播导致读取整体失败现在捕获后返回null该键被安全跳过其余键照常读取。集成测试returns all valid JSON data/returns null when reading invalid JSON value正是针对这一行为编写的回归用例。四、过滤模型prefix 与 allowList从 2.1.0 到 2.2.0过滤能力经历了两次升级最终形态是PreferencesFilter组合在shared_preferences_platform_interface的types.dart中定义方法平台接口层过滤语义getAll()/clear()仅作用于默认前缀flutter.getAllWithPrefix(prefix)/clearWithPrefix(prefix)2.1.0仅作用于指定前缀getAllWithParameters(GetAllParameters)/clearWithParameters(ClearParameters)2.2.0通过PreferencesFilter(prefix: ..., allowList: ...)组合过滤SharedPreferencesAsyncWeb各方法通过PreferencesFilters(allowList: ...)过滤在 Web 实现中过滤的核心是_getPrefixedKeys(prefix, allowList)与_getAllowedKeys(allowList)IterableString _getPrefixedKeys(String prefix, {SetString? allowList}) { return _getAllowedKeys(allowList: allowList).where((String key) key.startsWith(prefix)); } IterableString _getAllowedKeys({SetString? allowList}) { return html.window.localStorage.keys.where((String key) allowList?.contains(key) ?? true); }语义为先按 allowList 收窄键集合未提供时放行全部再按前缀过滤。集成测试中get all with allow listallowList 只含prefix.String则同前缀的其他键全部不可见与clearWithParameters with allow list只清除白名单内的prefix.StringList即为该组合行为的验证。allowList 机制的意义在于当把前缀设为空字符串以读取原生应用遗留数据时可以只挑选受支持类型的键避免因遇到不支持类型导致初始化失败主包 README 的 Adding, Removing, or changing prefixes 一节有完整说明。五、集成测试与验证方式本包的单元测试目录下只有一个指路测试tests_exist_elsewhere_test.dart打印提示本包使用 integration_test 进行测试请参见 example/README.md——这正是 2.0.1 版本把测试迁入 example 目录决策的延续。真实的测试位于 example/integration_test/shared_preferences_web_test.dart覆盖如下能力维度注册行为验证SharedPreferencesPlugin.registerWith(null)会把平台实例切换为 Web 实现registers itself。读写与类型往返对String/Bool/Int/Double/StringList五种类型执行 set/get 与 getAll 断言。前缀语义clear只清flutter.前缀键getAllWithPrefix(prefix.)只取对应前缀clearWithPrefix不误伤其他前缀clearWithNoPrefix验证空前缀清空一切。参数化过滤GetAllParameters/ClearParameters配合PreferencesFilter(prefix, allowList)的白名单行为。并发写入simultaneous writes用 100 个并发setValue验证最后一次写入生效的语义last-write-wins。JSON 容错returns all valid JSON data传统 API与returns null when reading invalid JSON value异步 API验证 2.4.3 的非 JSON 容错。异步 API 全量行为shared_preferences_async分组覆盖set/get各类型、getStringList可变性对应 2.4.2 修复、getPreferences/getKeys及其 allowList 过滤、clear及其过滤。测试通过IntegrationTestWidgetsFlutterBinding.ensureInitialized()与package:integration_test在真实浏览器中运行见 example/README.md测试入口依赖在 example/pubspec.yaml 中声明shared_preferences_web通过path: ../引用、web: ^1.0.0、integration_test来自 Flutter SDK。运行方式遵循 Flutter 官方 Web 集成测试流程例如先启动本地 Web 服务器再用flutter drive指定 Chrome 设备执行。六、工程使用速览在应用工程中使用本包能力时常规场景无需任何额外配置——只需在pubspec.yaml依赖shared_preferencesdependencies: shared_preferences: ^2.3.0 # 具体版本以实际可用版本为准Web 构建时会自动解析到shared_preferences_web。传统 API 直接await SharedPreferences.getInstance()后调用setInt/setString/setBool/setDouble/setStringList与对应 getter新工程建议使用SharedPreferencesAsync对应本包SharedPreferencesAsyncWeb实现或SharedPreferencesWithCache。若需要显式使用 Web 专属类型如SharedPreferencesWebOptions再手动添加shared_preferences_web依赖并直接 import。使用注意事项基于本包实现事实数据存储在浏览器 LocalStorage属于非关键数据存储官方 README 明确说明写入是异步落盘、不保证返回后已持久化不应存放关键数据。clear()只清理flutter.前缀键不会清空整个 LocalStorage。LocalStorage 中由其他代码写入的非 JSON 字符串会被安全跳过2.4.3不会导致读取崩溃但也不会被读取到。浏览器隐身模式、隐私策略或存储配额可能影响可用性Web 端数据与原生端不共享。七、版本能力对照速查表版本关键能力与变更0.1.0初始发布0.1.25声明 API 稳定性兼容 1.0.02.0.0空安全迁移2.0.1测试迁入 example改为 integration_test 方式运行2.0.2pubspec 补充implements: shared_preferences2.1.0新增getAllWithPrefix/clearWithPrefix2.2.0新增getAllWithParameters/clearWithParameters引入 filter 参数2.2.1补充 pub topics最低 Flutter 3.7/Dart 2.192.3.0Web 代码迁移到web: ^0.5.0最低 Dart 3.3/Flutter 3.192.4.0新增SharedPreferencesAsyncWeb2.4.1支持web: ^1.0.02.4.2修复getStringList返回不可变列表最低 Flutter 3.22/Dart 3.42.4.3修复非 JSON 字符串导致解析错误NEXT最低 SDK 升至 Flutter 3.38/Dart 3.10八、小结从 CHANGELOG 的十余次迭代可以看到shared_preferences_web的三条演进主线一是随联邦插件体系与 Flutter 工具链持续对齐 SDK 约束二是 API 能力从简单的getAll/clear走向 prefix、filter、allowList 直至全新的异步 API 体系三是围绕 Web 特有风险LocalStorage 全局性、JSON 类型往返、异构数据写入持续加固健壮性。理解这些版本背后的实现细节能帮助你在 Web 端正确选用 API、规避数据误清理并在遇到读取异常时快速定位到对应的修复版本。【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考