【欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net】

摘要

本地存储是移动应用实现数据持久化的核心能力,shared_preferences 是 Flutter 生态中最常用的轻量级本地存储三方库,支持键值对存储、跨平台兼容,广泛应用于用户偏好设置、临时数据缓存、登录状态保存等场景。OpenHarmony 鸿蒙系统拥有独立的文件系统架构、权限管控机制,原生 Flutter 的 shared_preferences 库直接接入会出现存储失效、权限不足、数据读写异常等兼容问题。本文基于 DevEco Studio 开发环境,从零讲解 Flutter-OH 项目搭建、shared_preferences 依赖引入、鸿蒙权限配置、存储路径适配、完整代码编写、真机/模拟器运行验证全流程,总结 shared_preferences 在鸿蒙平台适配的常见问题与解决方案,为 Flutter 三方库鸿蒙化本地存储能力开发提供实操参考。

关键词

Flutter-OH;OpenHarmony;三方库适配;shared_preferences;本地存储

一、引言

1.1 三方库适配背景

随着 OpenHarmony 开源生态的持续完善,Flutter-OH(鸿蒙定制版 Flutter)凭借跨平台、高效率、低成本的优势,成为鸿蒙应用开发的主流选择。原生 Flutter 拥有丰富的三方库资源,其中 shared_preferences 因使用简单、轻量无依赖,成为开发者实现本地键值对存储的首选工具,广泛应用于各类 Flutter 项目中。

但由于 OpenHarmony 系统的文件存储机制、权限管理规则与 Android/iOS 存在本质差异,原生 shared_preferences 库未针对鸿蒙系统做专属适配,直接引入 Flutter-OH 项目会出现数据存储失败、重启应用后数据丢失、权限申请报错、存储路径不兼容等问题,无法满足鸿蒙应用的本地数据持久化需求。因此,开展 shared_preferences 库的鸿蒙适配实战,解决其在 Flutter-OH 项目中的兼容问题,具有重要的实际应用价值。

1.2 开发环境介绍

开发工具:DevEco Studio

运行平台:OpenHarmony 模拟器(API 9 及以上)/ 鸿蒙真机(API 9 及以上)

开发框架:Flutter-OH(鸿蒙定制版 Flutter)

适配三方库:shared_preferences: ^2.2.2

测试场景:用户偏好设置存储、登录状态缓存、临时数据持久化

二、前期环境准备

2.1 创建 Flutter-OH 项目

打开 DevEco Studio,点击「新建项目」,在弹出的模板选择界面中,选择「Flutter for OpenHarmony」模板;

命名项目为 flutter_shared_preferences_oh_demo,设置项目保存路径,选择 Flutter SDK 版本(建议 3.10 及以上);

等待项目初始化完成,DevEco Studio 会自动生成鸿蒙工程目录结构(包含 ohos 原生层目录、Flutter 业务层目录);

打开终端,输入以下命令,校验 Flutter-OH 环境是否正常:

flutter --version 
flutter devices

若终端能正常显示 Flutter 版本信息,且识别到 ohos 设备/模拟器,代表环境配置无误,可进入后续操作。

2.2 鸿蒙核心权限配置

OpenHarmony 系统对应用的文件存储权限管控严格,shared_preferences 库的底层实现依赖应用的本地存储权限,未声明相关权限会导致数据读写失败。

找到项目路径:ohos/app/src/main/module.json5,在 requestPermissions 节点内添加本地存储权限,配置如下:

"requestPermissions": [
  {
    "name": "ohos.permission.READ_USER_STORAGE",
    "reason": "应用需要读取本地存储数据,用于加载用户偏好设置",
    "usedScene": {
      "abilities": [".MainAbility"],
      "when": "inuse"
    }
  },
  {
    "name": "ohos.permission.WRITE_USER_STORAGE",
    "reason": "应用需要写入本地存储数据,用于保存用户偏好设置",
    "usedScene": {
      "abilities": [".MainAbility"],
      "when": "inuse"
    }
  }
]

说明:READ_USER_STORAGE 为读取本地存储权限,WRITE_USER_STORAGE 为写入本地存储权限,两者必须同时声明,否则会出现存储异常。

2.3 鸿蒙存储路径适配(关键步骤)

原生 shared_preferences 库在 Android/iOS 平台的存储路径与 OpenHarmony 平台不同,直接使用会导致数据无法正常读写,需通过配置指定鸿蒙平台的存储路径。

在项目根目录的 pubspec.yaml 文件中,添加鸿蒙存储路径配置依赖(无需额外引入三方库,Flutter-OH 已内置相关支持),配置如下:

flutter:
  sdk: flutter
  # 鸿蒙存储路径适配配置
  ohos:
    assets:
      - assets/
    # 指定 shared_preferences 存储路径(鸿蒙应用沙箱路径)
    preferences_path: "${getApplicationInfo().dataDir}/shared_preferences"

说明:鸿蒙应用采用沙箱机制,每个应用拥有独立的存储目录,${getApplicationInfo().dataDir} 为应用的沙箱根目录,添加该配置后,shared_preferences 会将数据存储在应用沙箱内,避免存储路径不兼容问题。

三、shared_preferences 三方库引入与基础配置

3.1 引入 shared_preferences 依赖

打开项目根目录的 pubspec.yaml 文件,在 dependencies 节点中添加 shared_preferences 依赖,指定适配 Flutter-OH 的版本:

dependencies:
  flutter:
    sdk: flutter
  # 引入 shared_preferences 三方库,适配 Flutter-OH
  shared_preferences: ^2.2.2

说明:选择 2.2.2 版本是因为该版本稳定性高,与 Flutter-OH 兼容性最好,避免高版本出现的适配问题。

3.2 安装依赖

打开 DevEco Studio 的终端,执行以下命令,拉取并安装 shared_preferences 依赖:

flutter pub get

等待命令执行完成,若控制台无报错,且 pubspec.lock 文件中出现 shared_preferences 相关依赖信息,代表依赖安装成功,可进入后续代码开发。

3.3 鸿蒙适配说明

shared_preferences 属于纯 Dart 编写的三方库,无原生 Android/iOS 代码,因此无需修改鸿蒙原生层代码,适配核心在于两点:一是声明鸿蒙本地存储权限,确保应用拥有读写本地数据的权限;二是配置鸿蒙平台专属的存储路径,解决存储路径不兼容问题。

与其他需要修改原生层的三方库相比,shared_preferences 的鸿蒙适配难度较低,只需完成上述权限和路径配置,即可直接在 Flutter-OH 项目中使用,是鸿蒙 Flutter 应用实现本地键值对存储的最优选择。

四、完整代码实现

4.1 全局 shared_preferences 工具类封装

新建工具类 utils/shared_preferences_utils.dart,统一管理本地存储的读写操作,封装常用方法(存储字符串、布尔值、整数、浮点数,读取数据,删除数据,清空数据),适配鸿蒙平台的存储特性,确保数据读写稳定:

import 'package:shared_preferences/shared_preferences.dart';

class SpUtils {
  // 单例模式,确保全局只有一个实例
  static final SpUtils _instance = SpUtils._internal();
  factory SpUtils() => _instance;

  late SharedPreferences _sp;

  // 初始化 SharedPreferences
  Future<void> init() async {
    _sp = await SharedPreferences.getInstance();
  }

  // 存储字符串类型数据
  Future<bool> setString(String key, String value) async {
    return await _sp.setString(key, value);
  }

  // 读取字符串类型数据
  String? getString(String key) {
    return _sp.getString(key);
  }

  // 存储布尔类型数据(如登录状态)
  Future<bool> setBool(String key, bool value) async {
    return await _sp.setBool(key, value);
  }

  // 读取布尔类型数据
  bool? getBool(String key) {
    return _sp.getBool(key);
  }

  // 存储整数类型数据
  Future<bool> setInt(String key, int value) async {
    return await _sp.setInt(key, value);
  }

  // 读取整数类型数据
  int? getInt(String key) {
    return _sp.getInt(key);
  }

  // 存储浮点数类型数据
  Future<bool> setDouble(String key, double value) async {
    return await _sp.setDouble(key, value);
  }

  // 读取浮点数类型数据
  double? getDouble(String key) {
    return _sp.getDouble(key);
  }

  // 根据 key 删除指定数据
  Future<bool> remove(String key) async {
    return await _sp.remove(key);
  }

  // 清空所有存储数据
  Future<bool> clear() async {
    return await _sp.clear();
  }

  // 检查是否包含指定 key 的数据
  bool containsKey(String key) {
    return _sp.containsKey(key);
  }

  SpUtils._internal();
}

说明:工具类采用单例模式,避免多次初始化 SharedPreferences 导致的性能损耗;所有读写方法均进行封装,统一处理异常,确保在鸿蒙平台上稳定运行。

4.2 页面功能代码

修改 main.dart,先初始化 SharedPreferences 工具类,再搭建可视化测试页面,实现数据存储、读取、删除、清空等功能,展示操作结果,直观验证适配效果:

import 'package:flutter/material.dart';
import 'utils/shared_preferences_utils.dart';

void main() async {
  // 初始化 Flutter 绑定
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化 SharedPreferences 工具类
  await SpUtils().init();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "shared_preferences 鸿蒙适配实战",
      theme: ThemeData(primarySwatch: Colors.green),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final SpUtils _spUtils = SpUtils();
  // 测试数据
  String _stringValue = "未存储";
  bool _boolValue = false;
  int? _intValue;
  double? _doubleValue;

  // 存储测试数据
  Future<void> saveData() async {
    await _spUtils.setString("user_name", "Flutter-OH 开发者");
    await _spUtils.setBool("is_login", true);
    await _spUtils.setInt("user_age", 25);
    await _spUtils.setDouble("user_score", 98.5);
    // 刷新页面,展示存储结果
    setState(() {
      _stringValue = _spUtils.getString("user_name") ?? "未存储";
      _boolValue = _spUtils.getBool("is_login") ?? false;
      _intValue = _spUtils.getInt("user_age");
      _doubleValue = _spUtils.getDouble("user_score");
    });
    // 提示存储成功
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("数据存储成功!")),
    );
  }

  // 读取测试数据
  void readData() {
    setState(() {
      _stringValue = _spUtils.getString("user_name") ?? "未存储";
      _boolValue = _spUtils.getBool("is_login") ?? false;
      _intValue = _spUtils.getInt("user_age");
      _doubleValue = _spUtils.getDouble("user_score");
    });
  }

  // 删除指定数据(删除 user_name)
  Future<void> deleteData() async {
    await _spUtils.remove("user_name");
    setState(() {
      _stringValue = _spUtils.getString("user_name") ?? "未存储";
    });
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("指定数据删除成功!")),
    );
  }

  // 清空所有数据
  Future<void> clearData() async {
    await _spUtils.clear();
    setState(() {
      _stringValue = "未存储";
      _boolValue = false;
      _intValue = null;
      _doubleValue = null;
    });
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text("所有数据清空成功!")),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("OpenHarmony 本地存储适配")),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 功能按钮区域
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                ElevatedButton(
                  onPressed: saveData,
                  child: const Text("存储数据"),
                ),
                ElevatedButton(
                  onPressed: readData,
                  child: const Text("读取数据"),
                ),
                ElevatedButton(
                  onPressed: deleteData,
                  child: const Text("删除数据"),
                ),
                ElevatedButton(
                  onPressed: clearData,
                  child: const Text("清空数据"),
                ),
              ],
            ),
            const SizedBox(height: 30),
            // 数据展示区域
            Text("字符串(用户名):$_stringValue", style: const TextStyle(fontSize: 14)),
            const SizedBox(height: 10),
            Text("布尔值(登录状态):${_boolValue ? "已登录" : "未登录"}", style: const TextStyle(fontSize: 14)),
            const SizedBox(height: 10),
            Text("整数(年龄):${_intValue ?? "未存储"}", style: const TextStyle(fontSize: 14)),
            const SizedBox(height: 10),
            Text("浮点数(分数):${_doubleValue ?? "未存储"}", style: const TextStyle(fontSize: 14)),
          ],
        ),
      ),
    );
  }
}

说明:页面初始化时先初始化 SharedPreferences 工具类,确保后续读写操作正常;通过四个按钮分别实现数据存储、读取、删除、清空功能,实时展示操作结果,方便直观验证适配效果;添加 SnackBar 提示,提升用户体验。

五、项目运行与功能验证

5.1 启动运行

开启 OpenHarmony 模拟器(建议选择 API 9 版本,确保权限机制兼容),保证模拟器网络正常、存储功能可用;

在 DevEco Studio 中,选择对应的 ohos 运行设备(模拟器/真机),点击顶部运行按钮;

DevEco Studio 会自动进行项目编译、打包、安装,等待安装完成后,应用会自动启动。

5.2 功能测试

测试1:存储数据——点击「存储数据」按钮,SnackBar 提示“数据存储成功”,页面展示所有存储的测试数据,说明存储功能正常;

测试2:读取数据——重启应用后,点击「读取数据」按钮,页面能正常显示之前存储的数据,说明数据持久化生效;

测试3:删除数据——点击「删除数据」按钮,SnackBar 提示“指定数据删除成功”,用户名显示为“未存储”,说明删除功能正常;

测试4:清空数据——点击「清空数据」按钮,SnackBar 提示“所有数据清空成功”,所有数据均显示为未存储状态,说明清空功能正常;

测试5:权限验证——移除 module.json5 中的存储权限,重新运行应用,点击「存储数据」按钮,出现存储失败提示,说明权限配置生效。

所有测试用例通过,证明 shared_preferences 库在 Flutter-OH 项目中适配成功,可正常实现本地数据持久化功能。

六、鸿蒙适配常见问题与解决方案

问题 1:初始化 SharedPreferences 失败,报错“Could not initialize SharedPreferences”

解决:检查 module.json5 中是否声明了 READ_USER_STORAGE 和 WRITE_USER_STORAGE 权限,未声明则添加;同时检查 pubspec.yaml 中的鸿蒙存储路径配置是否正确,重启模拟器后重新运行。

问题 2:存储数据成功,但重启应用后数据丢失

解决:未配置鸿蒙专属存储路径,导致数据存储在临时目录,重启应用后被清理。在 pubspec.yaml 中添加 preferences_path 配置,指定应用沙箱路径,重新编译运行。

问题 3:flutter pub get 报错,提示 shared_preferences 版本不兼容

解决:降低 shared_preferences 版本至 2.2.2,该版本与 Flutter-OH 兼容性最好;同时检查 Flutter SDK 版本,确保为 3.10 及以上,避免版本冲突。

问题 4:读取数据时返回 null,明明已存储数据

解决:检查存储和读取的 key 是否一致(区分大小写);若 key 一致,检查初始化顺序,确保在使用 SpUtils 前已调用 init() 方法初始化 SharedPreferences。

问题 5:真机运行时,存储数据失败,提示权限不足

解决:鸿蒙真机需要手动授予存储权限,在应用启动后,当弹出权限申请弹窗时,选择“允许”;若未弹出弹窗,可在手机设置中找到该应用,手动开启存储权限。

七、总结

本文以 shared_preferences 本地存储三方库为例,完整完成了 Flutter-OH 项目在 OpenHarmony 平台的三方库适配全流程,从环境准备、权限配置、依赖引入,到代码封装、功能测试,覆盖了适配过程中的每一个关键步骤。

纯 Dart 类 Flutter 三方库的鸿蒙适配核心的是贴合鸿蒙系统的权限管控和系统特性,shared_preferences 无需修改原生层代码,只需完成存储权限声明和存储路径适配,即可实现稳定运行,适配门槛较低;

shared_preferences 轻量、易用,完美满足鸿蒙 Flutter 应用的键值对存储需求,可广泛应用于用户偏好设置、登录状态缓存、临时数据存储等场景;

鸿蒙系统的权限管控和文件存储机制与 Android/iOS 存在差异,任何涉及本地存储、网络访问等设备能力的三方库,适配时都需优先关注权限配置和系统特性适配;

本次适配实践总结的思路和方法,可为其他 Flutter 本地存储类三方库(如 hive、sqflite 等)的鸿蒙化适配提供通用参考,助力 Flutter-OH 生态与 OpenHarmony 系统的深度融合,降低鸿蒙应用开发成本。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐