news 2026/9/21 17:01:03

从版本演进看 shared_preferences_web:Flutter Web 端本地存储插件实现与升级指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从版本演进看 shared_preferences_web:Flutter Web 端本地存储插件实现与升级指南

从版本演进看 shared_preferences_web:Flutter Web 端本地存储插件实现与升级指南

【免费下载链接】pluginsPlugins for Flutter maintained by the Flutter team项目地址: https://gitcode.com/gh_mirrors/pl/plugins

shared_preferences_web 是 Flutter 官方维护的联邦插件体系中 Web 平台的实现,负责把shared_preferences的 API 映射到浏览器localStorage上。本文以本仓库中该包的 CHANGELOG.md 为脉络,梳理其版本演进历程,并结合 lib/shared_preferences_web.dart 的源码实现与集成测试,讲解 Web 端本地存储的底层原理、联邦插件注册机制,以及开发者升级到 2.x 时需要关注的破坏性变化。读完本文,你将掌握该插件的运行机制、测试方法与版本兼容要点。

一、版本演进全景:从 0.1.0 到 2.0.4

CHANGELOG 完整记录了该包从诞生到成熟的全部变更,可以清晰看出三条主线:平台适配工程质量空安全迁移

1. 早期阶段(0.1.0 ~ 0.1.2+8):补齐平台占位与依赖约束

  • 0.1.0:初始发布,随后在0.1.0+1中移除 pubspec 中废弃的author:字段,并要求 Flutter SDK ≥ 1.10.0。
  • 0.1.1:新增了配套的shared_preferences_macos包,联邦插件体系开始成型。
  • 0.1.2:提升 Flutter 版本下限,并添加 stub podspec 文件,为后续 Apple 平台接入做准备。
  • 0.1.2+1临时添加了一个空实现的android/目录,用于规避 Flutter issue #46898(Android 构建在缺少该目录时解析失败的问题)。这是联邦插件早期"占位目录"的典型做法。
  • 0.1.2+2 ~ 0.1.2+8:清理未使用的onMethodCall方法、升级 gradle 版本规避 Android 工程问题、显式声明 pedantic dev_dependency、将 Dart 下限提升到 2.1.0,最终在0.1.2+7移除 Android 占位目录,宣告该包正式回归纯 Web 实现。

从源码看,Web 实现根本不需要任何原生目录——lib/shared_preferences_web.dart 只依赖dart:htmlflutter_web_plugins,因此占位目录的移除与"声明 API 稳定性"(0.1.2+5)共同标志着该包走向成熟。

2. 2.0.0:空安全迁移的破坏性升级

2.0.0是唯一一个带破坏性语义的版本——迁移到 null-safety。这要求:

  • 使用方 Dart SDK 必须 ≥ 2.12.0;
  • 插件内部所有可空类型显式标注,例如源码中setValue(String valueType, String key, Object? value)Object?参数、registerWith(Registrar? registrar)的可空注册器。

3. 2.0.1 ~ 2.0.4:测试体系与代码质量收尾

  • 2.0.1:更新 README 安装说明;把测试迁移到 example 目录,改用flutter drive作为集成测试运行方式。这解释了为什么包的 test/tests_exist_elsewhere_test.dart 里只有一个打印提示的占位测试——真正的测试已全部迁往 example。
  • 2.0.2:在 pubspec 中为联邦插件添加implements声明(详见下文第三节)。
  • 2.0.3:修复新启用的 analyzer 选项告警,并移除对meta的依赖
  • 2.0.4:修复library_private_types_in_public_apisort_child_properties_lastuse_key_in_widget_constructors等 lint 警告。
  • NEXT(未发布):将最低 Flutter 版本提升至3.0

二、核心实现原理:localStorage 上的 JSON 编解码层

虽然 CHANGELOG 以变更条目为主,但对应版本的行为可以从 lib/shared_preferences_web.dart 中完整还原。整个实现只有约 80 行,围绕浏览器html.window.localStorage封装了四个核心操作:

方法对应 shared_preferences API底层行为
getAll()getKeys/get*系列遍历所有flutter.前缀键并逐个json.decode
setValue()setString/setBool/setInt/setDouble/setStringListjson.encode后写入localStorage[key]
remove()remove直接localStorage.remove(key)
clear()clear只移除flutter.前缀的键

实现中有三个值得注意的设计点:

  1. 键前缀校验_checkPrefix要求所有键必须以flutter.开头,否则抛出FormatException(源码 L53-L61)。这是为了避免污染同一域名下其他应用的数据。
  2. clear 的精确删除:源码注释明确强调不要使用localStorage.clear(),因为它会清掉该域名下所有站点的数据,而不仅是flutter.前缀键(源码 L22-L28)。
  3. 泛型恢复:JSON 往返会丢失泛型信息(List<String>解码后变成List<dynamic>),因此_decodeValue对 List 显式执行cast<String>()恢复 RTTI(源码 L75-L80)。

这正是2.0.0空安全迁移得以成立的基础——Object?值通过json.encode序列化,读取时再json.decode还原,整个编解码链路在 null-safety 下依然完整。

三、联邦插件结构:implements 声明与自动注册

2.0.2添加的implements是理解该包运行方式的关键。查看 pubspec.yaml:

flutter: plugin: implements: shared_preferences platforms: web: pluginClass: SharedPreferencesPlugin fileName: shared_preferences_web.dart

这表示shared_preferences_webshared_preferences联邦插件在 Web 端的认可(endorsed)实现。开发者只需在工程中依赖shared_preferences,Flutter 工具链在构建 Web 目标时会自动拉入本包,无需手动注册任何平台代码。

插件入口是 SharedPreferencesPlugin.registerWith,其内部只有一行核心逻辑:

SharedPreferencesStorePlatform.instance = SharedPreferencesPlugin();

即把SharedPreferencesStorePlatform(来自shared_preferences_platform_interface)的默认实例替换为 Web 实现。集成测试 shared_preferences_web_test.dart 专门验证了这一注册行为:先用MethodChannelSharedPreferencesStore占位,调用registerWith后断言实例已变为SharedPreferencesPlugin

四、测试体系:为什么测试都在 example 目录

CHANGELOG 2.0.1 提到的"Move tests toexampledirectory"需要结合测试文件理解。包级目录下 test/tests_exist_elsewhere_test.dart 只负责在flutter test时打印指引,说明真实测试位置;而真正的行为测试位于 example/integration_test/shared_preferences_web_test.dart,因为 Web 插件的dart:htmllocalStorage只能在真实浏览器环境中运行。

测试覆盖了本节前述的全部关键行为:

  • getAll:只返回flutter.前缀键,unprefixed_key被过滤;
  • setValue:断言写入值与json.encode结果一致,并验证StringList恢复为List<String>
  • remove / clear:验证非前缀键抛FormatExceptionclear保留非 Flutter 键;
  • registerWith:验证插件注册逻辑。

运行方式见 run_test.sh(依赖 chromedriver):

flutter drive -d web-server --web-port=7357 --browser-name=chrome \ --driver=test_driver/integration_test.dart \ --target=integration_test/shared_preferences_web_test.dart

五、升级到 2.x 的实操清单

综合 CHANGELOG 各版本约束,开发者迁移到shared_preferences_web2.x 需要满足:

  1. SDK 版本:Dart ≥ 2.12.0(2.0.0 空安全)、Flutter ≥ 3.0(NEXT 版本要求),pubspec 中已显式声明sdk: ">=2.12.0 <3.0.0"flutter: ">=3.0.0"
  2. 依赖方式:工程中只需依赖shared_preferences,无需直接声明本包(endorsed 机制自动引入);
  3. 键名规范:自定义键需以flutter.开头,否则运行时会抛FormatException
  4. 数据兼容性:Web 端数据以 JSON 字符串存储于localStorage,跨版本读取依赖编解码一致性,升级后旧键值仍可正常读取。

结语

从 0.1.0 的初始发布到 2.0.4 的 lint 收尾,CHANGELOG.md 完整折射出一个官方联邦插件走向稳定的全过程:平台占位的增删、空安全迁移、测试体系重构、工程质量收敛。而其 80 行的核心实现与详尽的集成测试,则为 Web 端本地存储提供了"麻雀虽小、五脏俱全"的最佳范本。读者如需深入,可继续查看 README.md 与同目录下的 pubspec.yaml。

【免费下载链接】pluginsPlugins for Flutter maintained by the Flutter team项目地址: https://gitcode.com/gh_mirrors/pl/plugins

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 16:49:19

C++调Deepseek流式输出难?让Codex走TaoToken通道排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 16:41:32

Relay 缓存复用完全指南:fetchPolicy、数据可用性与部分渲染实战

Relay 缓存复用完全指南&#xff1a;fetchPolicy、数据可用性与部分渲染实战 【免费下载链接】relay Relay is a JavaScript framework for building data-driven React applications. 项目地址: https://gitcode.com/gh_mirrors/relay29/relay Relay 在应用运行过程中会…

作者头像 李华