Flutter 鸿蒙实战:用 shared_preferences 三方库给应用做一套能记住你偏好的设置中心
欢迎加入 CPF-Flutter 鸿蒙社区: https://atomgit.com/CPF-Flutter
很多应用有"设置一下、下次打开还能记住"的需求:用户调了阅读模式、改了大字号、收藏了几个词条,希望下次进入还是老样子;如果每次重开都要重新设一遍,体验反而比不用还差。要在鸿蒙应用里做这种"本地偏好记忆",可以用 Flutter 官方生态里最常用的轻量键值对存储库——shared_preferences。
这次选了 shared_preferences,做了一个叫 偏好设置中心(LikeKeeper) 的小 Demo。功能很集中:昵称随手存、阅读模式开关、正文字号滑条、收藏词条增删、右上角一键清空。任何一项改完立即写入本地,杀掉 App 重开还在。登录状态、主题、引导页标记这类"要记住的小配置"都可以照这个方式接。
LikeKeeper 的完整源码已经放到 AtomGit,文章里的设置面板和测试代码都在这里:
项目仓库: likekeeper - AtomGit
本地偏好存储用的是 AtomGit 上维护的鸿蒙版本(flutter_packages 聚合仓库里的 shared_preferences 主包 + shared_preferences_ohos 的实现包),仓库链接统一放在文末。这库接入代码不多,这次花时间核对的主要是依赖:shared_preferences 的鸿蒙实现拆成了独立子包,主包、平台接口包、ohos 实现包三个要指到同一个提交,配错了就会被卡在版本解析。下面把实际跑通的配置和过程记下来。
环境和设备
还没搭好 Flutter 鸿蒙环境的话,可以先看《Flutter OHOS 开发环境搭建指南》,链接见文末。
我这边用的环境如下:
| 项目 | 版本 |
|---|---|
| Flutter | 3.35.8-ohos-1.0.3,channel [user-branch] |
| Dart | 3.9.2 |
| DevEco Studio | 26.0.0 |
| 编译 SDK | OpenHarmony SDK 26.0.0 |
| shared_preferences | 2.5.4(鸿蒙适配版) |
| 验证方式 | Pura 90 Pro 7.0.0(26.0.0) |
本文的 Demo 工程放在
C:盘。因为shared_preferences这类带原生插件(ohos 实现)的库,其插件源码由 pub 缓存在C:,若工程放在其他盘符会触发"相对路径/符号链接"类构建错误。工程与插件缓存同盘能少踩很多坑(详见 FAQ)。
先把依赖选对
这次用的是 shared_preferences 2.5.4,固定到提交 4a7a536bba8447c7d4eacde2fb1a2e0fbe2da044。它在 flutter_packages 聚合仓库里的路径是 packages/shared_preferences/shared_preferences。下面的配置可以直接放进应用的 pubspec.yaml:
dependencies:
shared_preferences:
git:
url: https://atomgit.com/CPF-Flutter/flutter_packages.git
ref: 4a7a536bba8447c7d4eacde2fb1a2e0fbe2da044
path: packages/shared_preferences/shared_preferences
dependency_overrides:
shared_preferences_platform_interface:
git:
url: https://atomgit.com/CPF-Flutter/flutter_packages.git
ref: 4a7a536bba8447c7d4eacde2fb1a2e0fbe2da044
path: packages/shared_preferences/shared_preferences_platform_interface
shared_preferences_ohos:
git:
url: https://atomgit.com/CPF-Flutter/flutter_packages.git
ref: 4a7a536bba8447c7d4eacde2fb1a2e0fbe2da044
path: packages/shared_preferences/shared_preferences_ohos
执行:
flutter pub get
shared_preferences 有两处容易配错。
一处是 path。仓库是聚合仓库,shared_preferences 要落到 packages/shared_preferences/shared_preferences 这个子目录,ohos 实现则在同一仓库的 packages/shared_preferences/shared_preferences_ohos。
另一处是 主包、平台接口包、ohos 实现包三者要配套。主包 shared_preferences 内部会依赖 shared_preferences_platform_interface 和 shared_preferences_ohos,如果用默认配置,pub 可能从 pub.dev 或内嵌仓库拉到跟主包不同源的版本,两头消息格式不一致。用 dependency_overrides 把平台接口包和 ohos 实现包都指到与主包相同的提交,三者才配套。改完重新 flutter pub get,在 pubspec.lock 里能看到 shared_preferences 2.5.4、shared_preferences_platform_interface 2.4.1、shared_preferences_ohos 2.5.4 均来自同一 AtomGit 提交。
选版本时要和本机 Flutter 对齐:这里
shared_preferences 2.5.4要求 Flutter>=3.35.0、Dart>=3.9.0,与本机3.35.8/3.9.2完全匹配,可直接用。
接口就一套读写,够用了
shared_preferences 的模型很单纯:一个单例对象,带类型的 get/set,外加删、清、查询。对外主要就 SharedPreferences 这一个类,所有方法几乎都是这一套的变体。
鸿蒙端底层封装的是 @ohos.data.preferences,把所有键值对序列化写到应用沙箱的本地文件里;Dart 侧通过平台通道读写这个单例。
Dart 端先导入:
import 'package:shared_preferences/shared_preferences.dart';
接口一:getInstance() —— 应用启动时先拿到单例
final SharedPreferences prefs = await SharedPreferences.getInstance();
它做一次性的"把磁盘上所有已存键值对读进内存",返回单例。后续所有读写都走这个对象。启动时或要用本地存储的地方先调它。
接口二:带类型写入 setXxx()
Future<bool> setString(String key, String value);
Future<bool> setBool(String key, bool value);
Future<bool> setInt(String key, int value);
Future<bool> setDouble(String key, double value);
Future<bool> setStringList(String key, List<String> value);
各方法都是 Future<bool>,返回是否写入成功;同一 key 重复写会覆盖旧值。存什么类型就用哪个方法:
await prefs.setString('nickname', '鸿小蒙'); // 存字符串
await prefs.setBool('nightMode', true); // 存开关
await prefs.setInt('fontSize', 16); // 存整数
await prefs.setStringList('favorites', ['Flutter', 'OpenHarmony']); // 存列表

接口三:带类型读取 getXxx()
String? getString(String key);
bool? getBool(String key);
int? getInt(String key);
double? getDouble(String key);
List<String>? getStringList(String key);
读取是同步的(数据已在内存里),key 不存在时返回 null,结合 ?? 给默认值:
final nickname = prefs.getString('nickname') ?? '';
final nightMode = prefs.getBool('nightMode') ?? false;
final fontSize = prefs.getInt('fontSize') ?? 14;
final favorites = prefs.getStringList('favorites') ?? [];
接口四:删除与清空 remove() / clear()
Future<bool> remove(String key); // 删单条
Future<bool> clear(); // 清空全部
退出登录清某条 token、设置页"一键清空"清掉全部偏好,都靠这两个:
await prefs.remove('nickname'); // 只删昵称
await prefs.clear(); // 清空所有键值对

接口五:查询 containsKey() / getKeys()
bool containsKey(String key); // 判断某个 key 是否存在
Set<String> getKeys(); // 取当前所有 key 的集合
if (!prefs.containsKey('firstLaunch')) { /* 首次启动 */ }
print(prefs.getKeys()); // 打印所有已存键

提示:
shared_preferences适合保存小而简单的偏好(开关、字符串、小列表)。不适合存大对象或敏感数据;大量结构化数据请用数据库。
接到设置面板上
LikeKeeper 以设置面板为主页:AppBar 带一个"清空全部"按钮,往下依次是用户资料(昵称)、外观(阅读模式、正文字号)、收藏(增删词条),底部实时显示当前已存的所有键。
进页面先 getInstance() 一次性读盘,把状态落进内存,再做任何修改时同步 setXxx 写回:
Future<void> _loadAll() async {
final prefs = await SharedPreferences.getInstance();
setState(() {
_prefs = prefs;
_nickname = prefs.getString('nickname') ?? '';
_nightMode = prefs.getBool('nightMode') ?? false;
_fontSize = prefs.getInt('fontSize') ?? 14;
_favorites = prefs.getStringList('favorites') ?? [];
});
}
// 任意一处修改,改动即写回
Future<void> _toggleNightMode(bool value) async {
await _prefs!.setBool('nightMode', value);
setState(() => _nightMode = value);
}
写后重启验证是这套存储的关键一步:flutter run 跑起来改几个设置,杀掉 App 再重新进入,面板应当原样恢复。定位"改了没生效"的问题时,先确认是不是真的重开过、再确认 get/set 成对、key 完全一致。
关键文件:lib/main.dart 是页面和读写逻辑,昵称框、开关、滑条、收藏 Chip 都在这一个文件里。_loadAll() 读盘、各 setXxx 写回、_clearAll() 清空。把它搬进多页面应用时,唯一要注意的就是各页面对 SharedPreferences 共享同一个单例——在一个页面 set,另一个页面 get 到的就是最新值。
下载源码,签名后装到手机
可以直接把 LikeKeeper 拉下来运行,依赖已经写进工程:
git clone https://atomgit.com/gcw_uKGkQkkd/likekeeper.git
cd likekeeper
flutter pub get
然后在 DevEco Studio 里完成调试签名:
-
用 DevEco Studio 打开
ohos目录。 -
进入 File → Project Structure → Signing Configs。
-
勾选 Automatically generate signature,给当前工程和设备生成签名,点 Apply/OK。
签名完成后构建、安装:
flutter build hap --release
hdc list targets
hdc -t <设备ID> install -r build/ohos/hap/entry-default-signed.hap
hdc -t <设备ID> shell aa start -a EntryAbility -b com.example.preferences_demo
平时调页面需要热重载,可用 flutter run -d <设备ID>。若构建停在签名环节或报你本机没有签名配置,先按上面第 3 步自动生成签名即可。
本机实际试了什么
静态检查与构建验证结果:
-
flutter analyze:通过,无问题。 -
flutter test:冒烟测试通过(用setMockInitialValues预置nickname/nightMode,验证页面能渲染并读回)。 -
flutter build hap --debug:HvigorassembleHap成功,产出ohos/entry/build/default/outputs/default/entry-default-unsigned.hap(约 91 MB)。注意未签名 HAP,装真机前需按上一节补齐调试签名。
真机上逐项操作后的结果如下:
| 操作 | 预期结果 |
|---|---|
| 输入昵称后点保存 | 立即显示"已存昵称",setString 返回 true |
| 打开阅读模式开关 | 状态变为"已开启",getBool 读到 true |
| 拖动正文字号滑条 | 跟随显示 x px,getInt 读到对应整数 |
| 点"添加收藏" | 底部多一个收藏 Chip,getStringList 读到新列表 |
| 点右上角"清空全部" | 昵称/开关/字号/收藏全部归默认,getKeys() 为空 |
| 改完杀进程重开 | 所有已存设置原样恢复(持久化生效) |
FAQ:接入时遇到的问题
找不到包,或提示 Dart SDK 版本不兼容
先看拉的是哪个分支/提交,再核对 path。shared_preferences 在聚合仓库里,pubspec.yaml 一定不要只写仓库 url,要带上 path: packages/shared_preferences/shared_preferences。本文用的 4a7a536… 对应本机 Flutter 3.35.8 / Dart 3.9.2,可直接用。若你本机 Flutter 更旧,建议换用该库对应的旧版适配分支。
报 "Filename too long" / 依赖解析就一直卡在 git checkout(Windows)
首次 flutter pub get 拉 flutter_packages 聚合仓库时,git 要 checkout 整个 monorepo,其中部分示例的长路径可能超过 Windows 默认 260 字符限制而失败。在终端执行一次:
git config --global core.longpaths true
开启长路径支持后,清掉刚才半途而废的缓存再重新 flutter pub get。缓存位置在 %PUB_CACHE%\git(本机是 C:\Users\<你>\Pub\Cache\git),把 flutter_packages-* 对应的目录删掉即可。
报 "pubspec for shared_preferences ... has version ..." 版本冲突
通常是因为主包与其依赖的平台接口包/ohos 实现包来源不一致(一个来自 git 适配仓库、一个来自 pub.dev),或第一次 checkout 失败留下了损坏的缓存。应对:dependency_overrides 把 shared_preferences_platform_interface、shared_preferences_ohos 都指到与主包相同的提交(见上文依赖节),并清理 %PUB_CACHE%\git 里的损坏缓存后重新 flutter pub get,再重建、装 HAP。
构建出 unsigned.hap,装不到设备
未签名 HAP 无法安装到真机。在 DevEco Studio 打开 ohos 目录 → File → Project Structure → Signing Configs → 勾选 Automatically generate signature(需登录华为账号、Profile 里包含你的设备),生成签名后重新 flutter build hap --release。
改了值,杀掉重开却没了
逐项排查:是否真的杀进程重开(热重载/热重启不会重读磁盘,直接 flutter run 重跑最稳);setXxx(key, value) 与 getXxx(key) 是否成对且 key 完全一致;写入是否拿到了返回值(false 表示写入失败)。shared_preferences 写的是本地文件,默认没有有效期,正常不会自动丢。
需要申请存储权限吗?
鸿蒙端用 @ohos.data.preferences 写入的是应用自己的沙箱目录,shared_preferences 不需要申请额外的存储权限就能读写。网络、文件、定位等权限和它无关。
发现库的问题,怎么反馈
1. 提交 Issue,说明问题和复现步骤
从文末链接进入 shared_preferences_ohos 鸿蒙适配仓库,打开 Issues 页面,先搜索有没有相同的问题。如果没有,点击右上角的 新建 Issue,填写问题标题和复现信息。

报告时把 pubspec.yaml 的依赖配置贴出来,再附上 pubspec.lock 中实际解析的主包/平台接口/ohos 包版本,说明预期什么、实际报什么错,以及 Flutter 版本、设备系统、提交号和关键日志。
2. Fork 项目,在自己的仓库中修改
如果问题能自己修,点击上游仓库右上角的 Fork。在 Fork 页面确认项目名称、自己的账号和要复制的分支,再点击 创建 Fork 项目。

Fork 完成后,把自己的仓库克隆到本地,并添加上游仓库。下面以补充 README 说明为例,<你的账号> 换成自己的 AtomGit 账号:
git clone https://atomgit.com/<你的账号>/flutter_packages.git
cd flutter_packages
git remote add upstream https://atomgit.com/CPF-Flutter/flutter_packages.git
git fetch upstream
git switch -c docs/ohos-shared-preferences-pr upstream/br_shared_preferences-v2.5.4_ohos
改好中文说明、检查差异后推到自己的 Fork:
git diff --check
git add [想提交的文件]
git commit -m "docs: clarify OHOS shared_preferences dependency pairing"
git push -u origin docs/ohos-shared-preferences-pr
3. 创建 PR,把修改提交给上游
推送后回到自己的 AtomGit Fork 仓库,点击 同步源项目,选择包含修改的分支。有超前提交时,可以通过弹窗中的 创建并提交 PR 进入 PR 创建页面。

在 PR 页面核对源仓库和源分支,目标仓库选 CPF-Flutter/flutter_packages 上游,目标分支按维护者当前要求选择。填写标题和说明,写清原来哪里配不对、改了什么、用哪个版本验证过;有对应 Issue 就关联上,确认差异后提交 PR。
相关链接
更多推荐


所有评论(0)