Flutter 鸿蒙:利用三方库构建待办清单

Flutter 开发实战:利用三方库构建鸿蒙原生体验的待办清单

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

一、教程简介

本教程面向鸿蒙开发新手,专注讲解 Flutter + 三方库 + 鸿蒙 跨端开发完整实践。我们将通过开发一个可持久化存储的待办清单应用,从零学习项目创建、三方库集成、代码编写、鸿蒙适配与真机运行,让你快速掌握 Flutter 开发鸿蒙应用的核心流程。

项目核心:使用 Flutter 跨端框架 + shared_preferences 三方库,实现支持鸿蒙 6.0+(API 20+)的原生体验待办 APP,关闭重启数据不丢失。


二、环境准备(必须配置)

  1. Flutter SDK:安装支持鸿蒙的正式版(3.13+),确保已切换至适配鸿蒙的分支,避免版本不兼容导致运行失败。

  2. DevEco Studio 4.0+:鸿蒙开发专用工具,需安装 API 20+(对应鸿蒙6.0+系统) 的 SDK,否则无法正常适配鸿蒙设备。

  3. 三方库shared_preferences: ^2.2.0,该库已完成鸿蒙端原生适配,无需额外修改代码,可直接用于鸿蒙本地存储。

  4. 设备:鸿蒙 6.0+ 真机(开启开发者模式、USB调试)或鸿蒙 6.0+ 模拟器,低版本鸿蒙设备无法运行本项目。


三、步骤一:创建 Flutter 鸿蒙项目

打开终端(Windows 用 cmd/PowerShell,macOS/Linux 用终端),执行以下命令,创建仅支持鸿蒙平台的 Flutter 项目:


flutter create --platforms ohos flutter_harmony_todo

说明:--platforms ohos 表示仅创建鸿蒙平台的项目,减少冗余文件,提升开发效率。

创建完成后,进入项目目录:


cd flutter_harmony_todo

四、步骤二:添加三方库依赖

  1. 打开项目根目录下的 pubspec.yaml 文件(该文件是 Flutter 项目的依赖配置文件)。

  2. dependencies 节点下,添加 shared_preferences 三方库依赖,完整配置如下(保留原有 Flutter 核心依赖):


name: flutter_harmony_todo
description: A new Flutter project for HarmonyOS with third-party library.
version: 1.0.0+1

environment:
  sdk: '>=3.1.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  # 核心三方库:鸿蒙适配的本地存储库,用于持久化待办数据
  shared_preferences: ^2.2.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true
  1. 保存 pubspec.yaml 文件后,在终端执行以下命令,安装三方库:

flutter pub get

注意:执行命令后,若出现 “pub get failed” 错误,大概率是网络问题,关闭代理、切换网络后重新执行即可;若提示版本不兼容,可将 shared_preferences 的版本调整为 ^2.2.0 及以上兼容版本。


五、步骤三:编写待办数据模型

数据模型用于规范待办事项的数据格式,方便后续存储和读取,步骤如下:

  1. lib 文件夹下,新建文件 todo_model.dart(右键 lib → New → File)。

  2. 复制以下代码到 todo_model.dart 中,每一行均有详细注释,便于理解:


// 待办事项数据模型类
// 作用:规范待办事项的格式(内容、完成状态),提供序列化/反序列化方法,适配本地存储
class TodoItem {
  String content;      // 待办任务内容(必填)
  bool isCompleted;    // 任务是否完成(默认未完成)

  // 构造函数:创建待办对象时,必须传入任务内容,完成状态可选(默认false)
  TodoItem({
    required this.content,  // required 表示该参数必须传入
    this.isCompleted = false, // 可选参数,默认值为false(未完成)
  });

  // 序列化方法:将 TodoItem 对象转为 Map 类型
  // 原因:shared_preferences 只能存储基本数据类型(字符串、数字等),无法直接存储对象
  Map<String, dynamic> toMap() {
    return {
      'content': content,      // 存储任务内容
      'isCompleted': isCompleted, // 存储完成状态
    };
  }

  // 反序列化方法:从 Map 类型转回 TodoItem 对象
  // 作用:读取本地存储的 Map 数据时,转为我们能直接使用的 TodoItem 对象
  factory TodoItem.fromMap(Map<String, dynamic> map) {
    return TodoItem(
      content: map['content'] ?? '', // 若读取不到内容,默认空字符串
      isCompleted: map['isCompleted'] ?? false, // 若读取不到状态,默认未完成
    );
  }
}

六、步骤四:主页面 + 核心逻辑(完整代码)

主页面是应用的核心,包含 UI 界面、用户交互、三方库调用(数据存储/读取),步骤如下:

  1. 打开 lib 文件夹下的 main.dart 文件(Flutter 项目的入口文件)。

  2. 删除原有默认代码,复制以下完整代码,注释详细,新手可逐行阅读理解:


// 导入所需依赖包
import 'package:flutter/material.dart'; // Flutter 核心UI组件库
import 'package:shared_preferences/shared_preferences.dart'; // 三方库:本地存储
import 'dart:convert'; // 用于 JSON 序列化/反序列化
import 'todo_model.dart'; // 导入我们编写的数据模型

// 程序入口:Flutter 应用启动时首先执行的代码
void main() {
  runApp(const MyApp());
}

// 根组件:无状态组件(无需动态更新)
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter 鸿蒙待办清单', // 应用标题(鸿蒙设备桌面显示)
      debugShowCheckedModeBanner: false, // 关闭调试标签(发布时必须关闭)
      theme: ThemeData(primarySwatch: Colors.blue), // 应用主题色(蓝色)
      home: const TodoPage(), // 应用首页(待办清单页面)
    );
  }
}

// 待办清单主页面:有状态组件(需要动态更新 UI,如添加待办、切换完成状态)
class TodoPage extends StatefulWidget {
  const TodoPage({super.key});

  // 创建状态对象(有状态组件必须重写该方法)
  @override
  State<TodoPage> createState() => _TodoPageState();
}

// 主页面状态类:处理页面的动态数据和交互逻辑
class _TodoPageState extends State<TodoPage> {
  // 待办列表:存储所有待办事项(泛型为我们定义的 TodoItem 类型)
  final List<TodoItem> _todoList = [];
  // 输入框控制器:用于获取输入框中的文本内容
  final TextEditingController _controller = TextEditingController();

  // 页面初始化方法:页面加载完成后首先执行
  @override
  void initState() {
    super.initState();
    _loadData(); // 初始化时,从鸿蒙本地读取已存储的待办数据
  }

  // ====================== 三方库核心操作(本地存储/读取) ======================
  // 从鸿蒙本地加载待办数据(异步方法,需用 async/await)
  Future<void> _loadData() async {
    // 1. 获取 shared_preferences 实例(连接鸿蒙本地存储)
    final prefs = await SharedPreferences.getInstance();
    // 2. 读取存储的待办数据(key 为 "todo_list",存储格式为 JSON 字符串)
    String? data = prefs.getString('todo_list');
    
    // 3. 若有数据,解析为 TodoItem 列表,更新 UI
    if (data != null) {
      List<dynamic> jsonList = jsonDecode(data); // JSON 字符串转列表
      setState(() {
        // 将列表中的每一个 Map 转为 TodoItem 对象,添加到待办列表
        _todoList.addAll(jsonList.map((e) => TodoItem.fromMap(e)).toList());
      });
    }
  }

  // 保存待办数据到鸿蒙本地(异步方法)
  Future<void> _saveData() async {
    // 1. 获取 shared_preferences 实例
    final prefs = await SharedPreferences.getInstance();
    // 2. 将待办列表转为 JSON 字符串(因为本地存储无法直接存储对象列表)
    String jsonData = jsonEncode(_todoList.map((e) => e.toMap()).toList());
    // 3. 存储数据(key 为 "todo_list",便于后续读取)
    await prefs.setString('todo_list', jsonData);
  }

  // ====================== 用户交互方法 ======================
  // 添加待办任务
  void _addTask() {
    // 1. 校验输入:输入框内容不为空(去除前后空格)
    if (_controller.text.trim().isNotEmpty) {
      setState(() {
        // 2. 向待办列表添加新任务(使用我们定义的 TodoItem 模型)
        _todoList.add(TodoItem(content: _controller.text.trim()));
      });
      // 3. 清空输入框
      _controller.clear();
      // 4. 保存新的待办列表到本地
      _saveData();
    }
  }

  // 切换待办任务的完成状态(传入任务索引,定位具体任务)
  void _toggleStatus(int index) {
    setState(() {
      // 取反完成状态(true ↔ false)
      _todoList[index].isCompleted = !_todoList[index].isCompleted;
    });
    // 切换状态后,保存更新后的列表到本地
    _saveData();
  }

  // ====================== UI 界面构建 ======================
  @override
  Widget build(BuildContext context) {
    // Scaffold:Flutter 标准页面容器,包含导航栏、主体内容
    return Scaffold(
      // 导航栏(顶部)
      appBar: AppBar(
        title: const Text("Flutter 鸿蒙待办清单"), // 导航栏标题
        centerTitle: true, // 标题居中
      ),
      // 主体内容(垂直布局:输入区 + 列表区)
      body: Column(
        children: [
          // 1. 输入区域:输入待办任务 + 添加按钮
          Padding(
            padding: const EdgeInsets.all(10), // 内边距(上下左右各10)
            child: Row(
              children: [
                // 输入框:占满剩余空间
                Expanded(
                  child: TextField(
                    controller: _controller, // 绑定输入框控制器
                    decoration: const InputDecoration(
                      hintText: "请输入待办事项", // 提示文本
                      border: OutlineInputBorder(), // 输入框边框
                    ),
                  ),
                ),
                const SizedBox(width: 10), // 输入框和按钮之间的间距
                // 添加按钮
                ElevatedButton(
                  onPressed: _addTask, // 点击触发添加任务方法
                  child: const Text("添加"), // 按钮文本
                ),
              ],
            ),
          ),

          // 2. 待办列表区:展示所有待办任务,可滚动
          Expanded(
            child: ListView.builder(
              itemCount: _todoList.length, // 列表项数量 = 待办列表长度
              // 列表项构建方法:每一个待办任务对应一个 ListTile
              itemBuilder: (context, index) {
                return ListTile(
                  // 待办任务内容
                  title: Text(
                    _todoList[index].content,
                    // 若任务完成,添加删除线
                    style: TextStyle(
                      decoration: _todoList[index].isCompleted
                          ? TextDecoration.lineThrough
                          : null,
                      color: _todoList[index].isCompleted ? Colors.grey : Colors.black,
                    ),
                  ),
                  // 右侧复选框:控制任务完成状态
                  trailing: Checkbox(
                    value: _todoList[index].isCompleted, // 绑定完成状态
                    // 点击复选框,切换完成状态
                    onChanged: (value) => _toggleStatus(index),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

七、步骤五:鸿蒙设备运行(关键步骤)

7.1 配置鸿蒙签名(必须操作)

鸿蒙系统要求所有应用必须签名才能运行,步骤如下:

  1. 打开 DevEco Studio,点击「File → Open」,选择 Flutter 项目根目录下的 ohos 文件夹(该文件夹是 Flutter 自动生成的鸿蒙工程目录)。

  2. 等待 DevEco Studio 加载鸿蒙工程完成后,点击「File → Project Structure」(或快捷键 Ctrl+Alt+Shift+S)。

  3. 在弹出的窗口中,选择「Project → Signing Configs」,点击「Auto Signing」(自动签名),系统会自动生成签名文件,无需手动配置。

  4. 点击「Apply → OK」,完成签名配置。

注意:若自动签名失败,需检查 DevEco Studio 是否登录华为开发者账号,且已安装鸿蒙 SDK(API 20+)。

7.2 连接设备/启动模拟器

  1. 真机连接:将鸿蒙 6.0+ 真机通过 USB 连接到电脑,开启手机的「开发者模式」和「USB 调试」(设置 → 关于手机 → 连续点击版本号 7 次,开启开发者模式;再进入系统和更新 → 开发者选项 → 开启 USB 调试)。

  2. 模拟器启动:打开 DevEco Studio,点击顶部工具栏的「AVD Manager」,创建并启动鸿蒙 6.0+ 模拟器(SDK 版本选择 API 20+)。

7.3 运行项目

  1. 回到终端,确保当前目录是 Flutter 项目根目录(flutter_harmony_todo)。

  2. 执行以下命令,将应用运行到鸿蒙设备/模拟器:


flutter run -d ohos

说明:-d ohos 表示指定运行到鸿蒙设备,若电脑连接了多个设备,可执行 flutter devices 查看设备ID,替换 ohos 为具体设备ID。

7.4 运行成功验证

运行成功后,鸿蒙设备/模拟器上会出现「Flutter 鸿蒙待办清单」应用,可进行以下操作验证功能:

  1. 在输入框中输入待办任务,点击「添加」,任务会显示在列表中。

  2. 点击任务右侧的复选框,可切换任务完成状态(完成后显示删除线)。

  3. 关闭应用,重新打开,之前添加的待办任务依然存在(三方库持久化生效)。


八、常见问题排查(新手必看)

问题现象 可能原因 解决方案
执行 flutter pub get 失败 网络问题、代理干扰、三方库版本不兼容 1. 关闭代理、切换手机热点;2. 将 shared_preferences 版本改为 ^2.2.0;3. 执行 flutter pub cache repair 修复缓存
鸿蒙设备无法识别 未开启 USB 调试、设备未连接、ADB 异常 1. 重新开启 USB 调试;2. 重新连接 USB 线;3. 重启电脑和手机
运行时提示「签名失败」 未配置鸿蒙签名、签名文件失效 重新配置自动签名,确保 DevEco Studio 登录开发者账号
应用启动后空白 代码错误、三方库未正确导入 检查 main.dart 代码是否完整,确保 shared_preferences 已成功安装
数据无法持久化 存储 key 错误、序列化/反序列化失败 检查 _saveData_loadData 方法,确保存储 key 为 “todo_list”,数据模型的序列化方法正确

九、核心知识点总结

  1. Flutter 与鸿蒙的关系:Flutter 是跨端框架,一套代码可直接运行在鸿蒙、Android、iOS 等平台,无需为鸿蒙单独编写 ArkTS 代码。

  2. 三方库的作用shared_preferences 简化了鸿蒙本地存储的开发,无需手动操作鸿蒙的 Preferences 数据库,直接调用 API 即可实现数据持久化。

  3. 有状态与无状态组件:无状态组件(如 MyApp)用于静态 UI,有状态组件(如 TodoPage)用于动态 UI(需更新数据、刷新界面)。

  4. 序列化与反序列化:由于本地存储无法直接存储对象,需将 TodoItem 对象转为 Map(序列化),读取时再转回 TodoItem(反序列化)。

运行截图如下
在这里插入图片描述

Logo

一站式 AI 云服务平台

更多推荐