Flutter for OpenHarmony 实战: HarmonyOS ArkTS API 24 待办事项清单 ​ - 今日待办事项记录

待办事项应用技术解析文档

一、项目背景概述

本项目是一个基于 Flutter 框架开发的待办事项(Todo)管理应用,专为 OpenHarmony 平台设计。应用的核心功能是帮助用户管理每日待办事项,支持添加新事项、标记完成状态以及删除事项等基本操作。

从产品定位来看,这是一个轻量级的效率工具类应用,采用简洁直观的界面设计,用户可以快速上手使用。应用预置了三条示例待办事项,包括 Flutter 项目开发、OpenHarmony 基础知识学习和技术分享材料准备,体现了其面向开发者群体的定位特征。

技术层面,应用采用 Flutter 的 Material Design 3 设计规范,使用深紫色作为主题色,整体视觉风格现代且统一。状态管理采用 Flutter 内置的 StatefulWidget 机制,通过 setState 进行局部状态更新,这种方案对于中小规模的待办应用来说足够简洁高效。

应用的整体架构采用组件化设计思想,将输入区域、列表展示和单个待办项拆分为独立的可复用组件,每个组件职责单一,便于维护和扩展。这种分层设计也体现了 Flutter 开发中"一切皆组件"的核心理念。

二、架构分析

2.1 整体架构图

应用入口 main

根组件 MaterialApp

首页组件 状态管理层

待办输入组件

列表视图 ListView.builder

待办项组件

复选框 Checkbox

文本展示 Text

删除按钮 IconButton

2.2 数据流图

列表视图 待办项组件 首页状态层 输入组件 用户 列表视图 待办项组件 首页状态层 输入组件 用户 输入文本并点击添加 验证输入非空 调用 onAddTodo(title) setState 添加新待办 触发重建,更新列表 点击复选框 调用 onToggle(id) setState 切换完成状态 触发重建,更新样式

2.3 架构层次说明

应用采用经典的三层组件架构模式:

第一层:应用根层级
负责应用的全局配置,包括主题、标题、调试标志等。使用 MaterialApp 作为根组件,提供 Material Design 风格的统一视觉规范。主题采用深紫色种子色生成的 ColorScheme,开启 Material 3 支持。

第二层:页面状态管理层
作为整个应用的状态中枢,管理所有待办事项的数据集合。维护待办事项列表、自增ID计数器等核心状态。提供添加、切换完成状态、删除等数据操作方法。通过回调函数将操作能力传递给子组件。

第三层:功能组件层
待办输入组件负责接收用户输入,验证输入有效性,触发添加操作。待办项组件负责展示单个待办事项的标题、完成状态,提供切换和删除交互。列表视图使用 ListView.builder 高效渲染待办列表,支持按需构建。

三、入口组件流程

3.1 应用启动流程

应用的入口函数是 main 函数,它调用 runApp 方法将根组件挂载到屏幕上。根组件是一个无状态组件,它的主要职责是配置应用级别的参数。

根组件的构建方法返回一个 MaterialApp 实例,配置了以下关键属性:

  • 应用标题为 “Flutter for openHarmony”
  • 主题使用 ColorScheme.fromSeed 基于深紫色自动生成完整的色彩方案
  • 启用 Material 3 设计规范
  • 关闭调试横幅,提供更干净的视觉体验
  • 首页设置为标题为 “Flutter for openHarmony” 的状态型首页组件

3.2 首页组件初始化

首页组件是一个状态型组件,它接收一个标题参数作为配置。其状态类在初始化时会创建三条预置的待办事项数据,每条数据包含 id、title 和 isCompleted 三个字段。同时初始化一个自增 ID 计数器,起始值为 4,用于后续新增待办事项的唯一标识。

首页的构建方法返回一个 Scaffold 脚手架组件,包含以下结构:

  • 顶部应用栏:标题为"今日待办事项",背景色为深紫色,前景色为白色
  • 主体内容:采用垂直列布局,上方是输入组件,下方是可滚动的列表视图
  • 列表视图使用 Expanded 包裹,确保列表占据剩余的全部可用空间

3.3 组件通信机制

首页组件与子组件之间通过回调函数进行通信:

  • 添加待办方法通过 onAddTodo 回调传递给输入组件,用于添加新待办
  • 切换状态方法通过 onToggle 回调传递给每个待办项组件,用于切换完成状态
  • 删除方法通过 onDelete 回调传递给每个待办项组件,用于删除待办

这种回调通信模式是 Flutter 中最基础也是最常用的组件间通信方式,适合父子组件之间的直接交互。

四、核心组件逐段解析

4.1 待办输入组件

待办输入组件是一个状态型组件,负责接收用户输入并触发添加操作。组件内部维护一个文本编辑控制器,用于管理输入框的文本内容。

组件结构分析:

组件的外部接口只接收一个回调函数 onAddTodo,当用户确认添加时调用此回调并将输入文本作为参数传递。这种设计将输入验证和添加逻辑解耦,输入组件只负责收集和验证用户输入,具体的数据操作交由父组件处理。

状态管理:
文本编辑控制器在组件初始化时创建,在组件销毁时通过 dispose 方法释放资源,避免内存泄漏。这是 Flutter 中处理表单输入的标准模式,通过控制器可以获取、设置、清空输入内容。

添加逻辑:
添加方法首先获取输入文本并去除首尾空白字符,然后进行非空判断:

  • 如果文本不为空,调用父组件传入的回调函数,并清空输入框
  • 如果文本为空,通过 ScaffoldMessenger 显示一个持续 2 秒的提示信息

界面布局:
输入组件的视觉容器使用 Container 包裹,设置了外边距、内边距、白色背景、圆角边框和轻微的阴影效果,营造出卡片式的视觉层次。

内部采用水平行布局,左侧是占据剩余空间的输入框,右侧是添加按钮:

  • 输入框使用 TextField,没有边框,设置了占位提示文字
  • 支持键盘提交事件,用户按下回车键也可以触发添加操作
  • 添加按钮使用 ElevatedButton,深紫色背景,白色文字,圆角矩形样式

4.2 待办项组件

待办项组件是一个无状态组件,负责展示单个待办事项的内容和状态。它接收四个参数:标题文本、完成状态、切换回调和删除回调。

设计理念:
作为无状态组件,待办项完全由父组件传入的数据驱动,自身不维护任何状态。这种设计遵循了 Flutter 的响应式编程思想,组件的外观完全由输入属性决定,便于测试和复用。

视觉呈现:
待办项同样采用卡片式设计,具有白色背景、圆角和阴影。内部是水平行布局,从左到右依次是:

  • 复选框:使用 Checkbox 组件,激活颜色为深紫色,点击触发切换回调
  • 标题文本:使用 Expanded 占据剩余空间,根据完成状态动态调整样式
    • 未完成时:黑色文字,无装饰线
    • 已完成时:灰色文字,带有删除线装饰
  • 删除按钮:使用 IconButton,红色垃圾桶图标,点击触发删除回调

状态视觉反馈:
组件通过文字颜色和删除线两种视觉手段清晰地表达待办事项的完成状态,符合用户的认知习惯。当任务完成时,文字变灰并添加删除线,视觉上弱化已完成事项的存在感,帮助用户将注意力集中在未完成的任务上。

4.3 独立待办列表组件

项目中还包含一个独立的待办列表组件,它封装了完整的待办列表管理功能,包括数据存储和操作方法。这个组件内部维护自己的待办列表数据和自增ID,提供切换完成状态、删除和添加等方法。

列表组件使用 ListView.builder 来构建可滚动列表,这种构建方式是懒加载的,只会构建当前可见的列表项,对于长列表性能更优。

此外,该组件还通过 Dart 的 extension 扩展机制提供了一个外部访问添加方法的途径,这是一种较为特殊的实现方式,展示了 Dart 语言扩展功能的灵活运用。

五、状态管理

5.1 状态架构

本应用采用 Flutter 内置的状态管理方案,即通过 StatefulWidget 和 setState 进行状态管理。这种方案的特点是简单直接,适合中小型应用。

状态分层:

  • 全局页面状态:由首页组件管理,包括待办事项列表和自增ID
  • 组件局部状态:由各子组件管理,如输入组件的文本控制器

状态更新机制:
所有状态变更都通过 setState 方法触发,这会通知 Flutter 框架重新构建受影响的组件树。setState 接收一个函数参数,在函数内修改状态变量,框架会在状态修改完成后调度一次重建。

5.2 核心状态变量

待办事项列表

  • 类型:列表,元素为键值对映射
  • 存储结构:每条待办包含 id(整数)、title(字符串)、isCompleted(布尔值)
  • 初始数据:三条预置的待办事项

自增ID计数器

  • 类型:整数
  • 作用:为新增的待办事项生成唯一标识符
  • 初始值:4

5.3 状态操作方法

添加待办
接收标题字符串作为参数,创建一个新的映射对象,使用当前的自增ID作为id,将新待办添加到列表末尾,自增ID计数器加1。整个操作包裹在 setState 中以触发界面更新。

切换完成状态
接收待办ID作为参数,使用 firstWhere 方法在列表中查找对应ID的待办项,将该待办的完成状态字段取反。操作在 setState 中执行。

删除待办
接收待办ID作为参数,使用 removeWhere 方法移除所有匹配ID的待办项,由于ID是唯一的,实际只会移除一项。操作在 setState 中执行。

六、关键代码详解

6.1 待办添加机制

添加待办的逻辑分布在两个组件中协同工作:

输入组件负责用户交互层面的验证,确保只有非空输入才会触发添加操作。它首先调用 trim 方法去除输入文本两端的空白字符,然后检查是否为空字符串。这种验证方式有效防止了用户添加纯空白的无效待办事项。

首页组件负责数据层面的添加操作,它接收验证后的标题文本,构造一个包含 id、title、isCompleted 三个字段的映射对象,添加到列表中。自增ID的使用保证了每个待办项都有唯一标识,这对于后续的查找、切换和删除操作至关重要。

6.2 状态切换实现

切换待办完成状态的核心代码使用了 firstWhere 方法,在列表中查找 ID 匹配的待办项,然后直接修改其完成状态属性。由于映射是引用类型,修改操作会直接反映到原列表中的对应元素上,不需要重新赋值。

这种实现方式简洁高效,但需要注意的是,它依赖于列表中的元素是可变的映射对象。如果使用不可变的数据模型类,则需要采用替换元素的方式来实现状态更新。

6.3 列表构建优化

列表视图使用 ListView.builder 构造函数,这是 Flutter 中构建长列表的推荐方式。与普通的 ListView 不同,builder 模式采用懒加载策略:

  • itemCount 参数指定列表的总长度
  • itemBuilder 是一个函数,接收上下文和索引,返回对应位置的组件
  • 框架只会构建当前可见区域内的列表项,以及少量的缓存区域
  • 当用户滚动时,离开可视区域的列表项会被销毁,新进入的会被构建

这种机制大大提升了长列表的性能,尤其是在待办事项数量较多时效果更明显。

6.4 输入资源管理

输入组件中对文本编辑控制器的管理体现了良好的资源管理实践:在状态类中创建控制器实例,在 dispose 生命周期方法中调用控制器的 dispose 方法,确保在组件销毁时释放控制器占用的资源。

这是 Flutter 开发中的一项重要最佳实践,如果不正确释放控制器、动画等资源,可能会导致内存泄漏问题。

七、技术总结

7.1 技术亮点

组件化设计:应用将功能拆分为输入组件、待办项组件、列表组件等独立单元,每个组件职责单一,接口清晰,便于单独测试和复用。

Material Design 3:采用最新的 Material 3 设计规范,使用 ColorScheme.fromSeed 自动生成配色方案,确保视觉风格的一致性和专业性。

响应式状态管理:通过 setState 实现状态驱动的界面更新,遵循 Flutter 的响应式编程范式,状态变化自动反映到界面上。

用户体验细节:空输入时的提示信息、已完成事项的视觉弱化(灰色+删除线)、卡片式布局和阴影效果营造层次感、支持键盘回车提交。

7.2 可优化点

数据持久化:当前所有待办数据都存储在内存中,应用重启后数据会丢失。可以引入本地存储方案实现数据持久化。

状态管理升级:对于更复杂的待办应用(如分类、标签、排序、搜索等功能),当前的 setState 方案可能不够用,可以考虑使用 Provider、Riverpod、Bloc 等状态管理库。

数据模型优化:当前使用映射存储待办数据,缺乏类型安全。可以定义一个 Todo 数据模型类,使用强类型提升代码的可维护性和安全性。

动画效果:可以添加列表项的插入/删除动画、完成状态切换动画等,提升用户体验的流畅度。

7.3 技术价值

本项目作为一个基础的待办事项应用,展示了 Flutter 开发的多个核心概念和最佳实践,包括组件化开发、状态管理、用户输入处理、列表构建等。对于 Flutter 初学者而言,这是一个很好的学习范本,可以帮助理解 Flutter 的基本开发模式和设计思想。

同时,项目针对 OpenHarmony 平台的适配也展示了 Flutter 跨平台开发的优势,同一套代码可以在不同平台上运行,大大降低了多平台应用的开发和维护成本。

请添加图片描述

Flutter for OpenHarmony 实战: 待办事项清单 ​ - 今日待办事项记录

前言:跨生态开发的新机遇

在移动开发领域,我们总是面临着选择与适配。今天,你的Flutter应用在Android和iOS上跑得正欢,明天可能就需要考虑一个新的平台:HarmonyOS(鸿蒙)。这不是一道选答题,而是很多团队正在面对的现实。

Flutter的优势很明确——写一套代码,就能在两个主要平台上运行,开发体验流畅。而鸿蒙代表的是下一个时代的互联生态,它不仅仅是手机系统,更着眼于未来全场景的体验。将现有的Flutter应用适配到鸿蒙,听起来像是一个“跨界”任务,但它本质上是一次有价值的技术拓展:让产品触达更多用户,也让技术栈覆盖更广。

不过,这条路走起来并不像听起来那么简单。Flutter和鸿蒙,从底层的架构到上层的工具链,都有着各自的设计逻辑。会遇到一些具体的问题:代码如何组织?原有的功能在鸿蒙上如何实现?那些平台特有的能力该怎么调用?更实际的是,从编译打包到上架部署,整个流程都需要重新摸索。
这篇文章想做的,就是把这些我们趟过的路、踩过的坑,清晰地摊开给你看。我们不会只停留在“怎么做”,还会聊到“为什么得这么做”,以及“如果出了问题该往哪想”。这更像是一份实战笔记,源自真实的项目经验,聚焦于那些真正卡住过我们的环节。

无论你是在为一个成熟产品寻找新的落地平台,还是从一开始就希望构建能面向多端的应用,这里的思路和解决方案都能提供直接的参考。理解了两套体系之间的异同,掌握了关键的衔接技术,不仅能完成这次迁移,更能积累起应对未来技术变化的能力。

混合工程结构深度解析

项目目录架构

当Flutter项目集成鸿蒙支持后,典型的项目结构会发生显著变化。以下是经过ohos_flutter插件初始化后的项目结构:

my_flutter_harmony_app/
├── lib/                          # Flutter业务代码(基本不变)
│   ├── main.dart                 # 应用入口
│   ├── home_page.dart           # 首页
│   └── utils/
│       └── platform_utils.dart  # 平台工具类
├── pubspec.yaml                  # Flutter依赖配置
├── ohos/                         # 鸿蒙原生层(核心适配区)
│   ├── entry/                    # 主模块
│   │   └── src/main/
│   │       ├── ets/              # ArkTS代码
│   │       │   ├── MainAbility/
│   │       │   │   ├── MainAbility.ts       # 主Ability
│   │       │   │   └── MainAbilityContext.ts
│   │       │   └── pages/
│   │       │       ├── Index.ets           # 主页面
│   │       │       └── Splash.ets          # 启动页
│   │       ├── resources/        # 鸿蒙资源文件
│   │       │   ├── base/
│   │       │   │   ├── element/  # 字符串等
│   │       │   │   ├── media/    # 图片资源
│   │       │   │   └── profile/  # 配置文件
│   │       │   └── en_US/        # 英文资源
│   │       └── config.json       # 应用核心配置
│   ├── ohos_test/               # 测试模块
│   ├── build-profile.json5      # 构建配置
│   └── oh-package.json5         # 鸿蒙依赖管理
└── README.md

目录

展示效果图片

flutter 实时预览 效果展示

运行到鸿蒙虚拟设备中效果展示

功能代码实现

本次开发中,我们采用了组件化的开发方式,将待办事项清单功能拆分为多个独立的组件,提高了代码的可维护性和复用性。以下是各个组件的详细实现:

1. TodoItem 组件

组件概述

TodoItem 组件用于展示单个待办事项项,包含待办事项标题、完成状态和删除功能。

实现代码

import 'package:flutter/material.dart';

class TodoItem extends StatelessWidget {
  final String title;
  final bool isCompleted;
  final Function(bool?) onToggle;
  final Function() onDelete;

  const TodoItem({
    Key? key,
    required this.title,
    required this.isCompleted,
    required this.onToggle,
    required this.onDelete,
  }) : super(key: key);

  
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.1),
            spreadRadius: 1,
            blurRadius: 3,
            offset: const Offset(0, 1),
          ),
        ],
      ),
      child: Row(
        children: [
          Checkbox(
            value: isCompleted,
            onChanged: onToggle,
            activeColor: Colors.deepPurple,
          ),
          Expanded(
            child: Text(
              title,
              style: TextStyle(
                fontSize: 16,
                decoration: isCompleted ? TextDecoration.lineThrough : null,
                color: isCompleted ? Colors.grey : Colors.black,
              ),
            ),
          ),
          IconButton(
            onPressed: onDelete,
            icon: const Icon(Icons.delete, color: Colors.red),
            splashRadius: 20,
          ),
        ],
      ),
    );
  }
}

技术要点

  • 状态管理:通过构造函数接收外部传入的状态和回调函数
  • 视觉反馈:根据 isCompleted 状态显示不同的文本样式(完成状态时显示划线效果)
  • 交互设计:添加了复选框和删除按钮,提供直观的用户交互
  • 布局优化:使用 Expanded 组件确保文本内容能够自适应布局

使用方法

TodoItem(
  title: todo['title'],
  isCompleted: todo['isCompleted'],
  onToggle: (value) => _toggleTodo(todo['id']),
  onDelete: () => _deleteTodo(todo['id']),
);

2. TodoInput 组件

组件概述

TodoInput 组件用于添加新的待办事项,包含文本输入框和添加按钮。

实现代码

import 'package:flutter/material.dart';

class TodoInput extends StatefulWidget {
  final Function(String) onAddTodo;

  const TodoInput({Key? key, required this.onAddTodo}) : super(key: key);

  
  _TodoInputState createState() => _TodoInputState();
}

class _TodoInputState extends State<TodoInput> {
  final TextEditingController _controller = TextEditingController();

  
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _addTodo() {
    final text = _controller.text.trim();
    if (text.isNotEmpty) {
      widget.onAddTodo(text);
      _controller.clear();
    } else {
      // 显示提示信息,当用户没有输入任何文本时
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(
          content: Text('请输入待办事项内容'),
          duration: Duration(seconds: 2),
        ),
      );
    }
  }

  
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
      padding: const EdgeInsets.all(8),
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.1),
            spreadRadius: 1,
            blurRadius: 3,
            offset: const Offset(0, 1),
          ),
        ],
      ),
      child: Row(
        children: [
          Expanded(
            child: TextField(
              controller: _controller,
              decoration: const InputDecoration(
                hintText: '添加今日待办事项...',
                border: InputBorder.none,
                contentPadding: EdgeInsets.symmetric(horizontal: 12),
              ),
              onSubmitted: (value) {
                _addTodo();
              },
            ),
          ),
          ElevatedButton(
            onPressed: _addTodo,
            style: ElevatedButton.styleFrom(
              backgroundColor: Colors.deepPurple,
              foregroundColor: Colors.white,
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(6),
              ),
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
            ),
            child: const Text('添加'),
          ),
        ],
      ),
    );
  }
}

技术要点

  • 状态管理:使用 StatefulWidget 管理输入框的状态
  • 文本控制器:使用 TextEditingController 控制文本输入和清除
  • 用户反馈:当用户未输入文本时,显示 SnackBar 提示信息
  • 布局设计:使用 RowExpanded 组件实现输入框和按钮的灵活布局

使用方法

TodoInput(onAddTodo: _addTodo);

3. 主页面集成

页面概述

主页面集成了 TodoInput 和 TodoItem 组件,实现了完整的待办事项清单功能。

实现代码

import 'package:flutter/material.dart';
import 'components/todo_input.dart';
import 'components/todo_item.dart';

void main() {
  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter for openHarmony',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(title: 'Flutter for openHarmony'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final List<Map<String, dynamic>> _todos = [
    {'id': 1, 'title': '完成 Flutter 项目开发', 'isCompleted': false},
    {'id': 2, 'title': '学习 OpenHarmony 基础知识', 'isCompleted': false},
    {'id': 3, 'title': '准备技术分享材料', 'isCompleted': false},
  ];

  int _nextId = 4;

  void _addTodo(String title) {
    setState(() {
      _todos.add({
        'id': _nextId++,
        'title': title,
        'isCompleted': false,
      });
    });
  }

  void _toggleTodo(int id) {
    setState(() {
      final todo = _todos.firstWhere((todo) => todo['id'] == id);
      todo['isCompleted'] = !todo['isCompleted'];
    });
  }

  void _deleteTodo(int id) {
    setState(() {
      _todos.removeWhere((todo) => todo['id'] == id);
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('今日待办事项'),
        backgroundColor: Colors.deepPurple,
        foregroundColor: Colors.white,
      ),
      body: Column(
        children: <Widget>[
          TodoInput(onAddTodo: _addTodo),
          Expanded(
            child: ListView.builder(
              itemCount: _todos.length,
              itemBuilder: (context, index) {
                final todo = _todos[index];
                return TodoItem(
                  title: todo['title'],
                  isCompleted: todo['isCompleted'],
                  onToggle: (value) => _toggleTodo(todo['id']),
                  onDelete: () => _deleteTodo(todo['id']),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

技术要点

  • 状态管理:使用 StatefulWidget 管理待办事项列表的状态
  • 列表渲染:使用 ListView.builder 高效渲染待办事项列表
  • 数据结构:使用 List<Map<String, dynamic>> 存储待办事项数据
  • 状态更新:使用 setState 方法更新 UI 状态

核心功能

  1. 添加待办事项:通过 TodoInput 组件输入待办事项内容,点击添加按钮或按回车键添加
  2. 切换完成状态:点击待办事项前的复选框,切换待办事项的完成状态
  3. 删除待办事项:点击待办事项后的删除按钮,删除对应的待办事项
  4. 初始数据:内置了3条示例待办事项,方便直接查看效果

本次开发中容易遇到的问题

1. 点击添加按钮无反应

问题描述

用户在输入框中未输入任何文本时,点击添加按钮没有任何反应。

原因分析

代码中添加了条件判断,只有当输入文本不为空时才会执行添加操作:

if (text.isNotEmpty) {
  widget.onAddTodo(text);
  _controller.clear();
}

解决方案

添加用户反馈,当用户未输入文本时,显示提示信息:

if (text.isNotEmpty) {
  widget.onAddTodo(text);
  _controller.clear();
} else {
  // 显示提示信息,当用户没有输入任何文本时
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(
      content: Text('请输入待办事项内容'),
      duration: Duration(seconds: 2),
    ),
  );
}

2. 组件通信问题

问题描述

在开发过程中,需要在不同组件之间传递数据和回调函数。

原因分析

Flutter 中组件之间的通信需要通过构造函数传递参数和回调函数。

解决方案

使用构造函数参数传递回调函数:

// 在 TodoInput 组件中
final Function(String) onAddTodo;

// 在主页面中传递回调
TodoInput(onAddTodo: _addTodo);

3. 状态管理问题

问题描述

待办事项列表的状态需要在多个操作中保持一致。

原因分析

添加、切换完成状态和删除操作都会修改待办事项列表的状态。

解决方案

将状态管理集中在主页面,使用 setState 方法更新状态:

void _addTodo(String title) {
  setState(() {
    _todos.add({
      'id': _nextId++,
      'title': title,
      'isCompleted': false,
    });
  });
}

4. 列表渲染性能问题

问题描述

当待办事项数量较多时,可能会影响页面的渲染性能。

原因分析

直接使用 ListView 渲染大量数据会导致性能问题。

解决方案

使用 ListView.builder 高效渲染列表:

ListView.builder(
  itemCount: _todos.length,
  itemBuilder: (context, index) {
    final todo = _todos[index];
    return TodoItem(
      title: todo['title'],
      isCompleted: todo['isCompleted'],
      onToggle: (value) => _toggleTodo(todo['id']),
      onDelete: () => _deleteTodo(todo['id']),
    );
  },
);

总结本次开发中用到的技术点

1. 组件化开发

  • 组件拆分:将待办事项清单功能拆分为 TodoItem 和 TodoInput 组件
  • 组件通信:通过构造函数传递参数和回调函数
  • 代码复用:提高了代码的可维护性和复用性

2. 状态管理

  • StatefulWidget:使用 StatefulWidget 管理组件的状态
  • setState:使用 setState 方法更新 UI 状态
  • TextEditingController:使用 TextEditingController 管理文本输入

3. 布局设计

  • Flex 布局:使用 Row、Column、Expanded 等组件实现灵活的布局
  • 容器组件:使用 Container 组件添加边距、填充和装饰
  • 列表渲染:使用 ListView.builder 高效渲染列表

4. 用户交互

  • 点击事件:使用 onPressed 处理按钮点击事件
  • 复选框:使用 Checkbox 组件实现完成状态的切换
  • 文本输入:使用 TextField 组件实现文本输入
  • 用户反馈:使用 SnackBar 组件显示提示信息

5. 数据结构

  • List<Map<String, dynamic>>:使用列表和映射存储待办事项数据
  • 唯一标识:为每个待办事项分配唯一的 ID,方便进行操作

6. 视觉设计

  • 主题配置:使用 ThemeData 配置应用主题
  • 阴影效果:为组件添加阴影效果,提升视觉层次感
  • 颜色搭配:使用深紫色作为主题色,搭配白色和灰色
  • 字体样式:根据待办事项的完成状态,使用不同的字体样式

7. 性能优化

  • 列表渲染:使用 ListView.builder 实现懒加载,提高渲染性能
  • 资源管理:在组件销毁时,正确释放 TextEditingController 资源

8. 平台适配

  • Flutter for OpenHarmony:使用 Flutter 开发可在 OpenHarmony 平台运行的应用
  • 跨平台兼容:代码可在 Android、iOS 和 OpenHarmony 平台运行

本次开发通过组件化的方式,实现了一个功能完整、交互友好的待办事项清单应用,展示了 Flutter for OpenHarmony 的开发能力。通过合理的代码组织和状态管理,确保了应用的性能和可维护性。

请添加图片描述

flutter_openHarmony(简称 Flutter‑OH)

注意:不是Google官方产物,是OpenHarmony社区TPC组织维护的Flutter引擎移植版本。把Flutter的Dart/Skia引擎做底层改造,让Flutter应用可以直接编译输出 HAP包,跑在OpenHarmony/纯血鸿蒙设备上,不需要依赖Android兼容层。

简单讲:一套Dart/Flutter业务代码,可以同时编译 Android、iOS、OpenHarmony(HAP)

核心原理

对Flutter Engine做Embedder嵌入适配,对接OpenHarmony Rosen图形管线、UIAbility生命周期,通过MethodChannel实现 Dart ↔ ArkTS双向通信,Flutter自绘UI渲染到鸿蒙Surface,复用方舟编译器、系统权限、分布式能力。

  • Dart业务代码几乎不变
  • 底层引擎适配鸿蒙图形、线程、生命周期
  • 输出产物是标准HAP应用包,可上架鸿蒙应用市场

主要优势

  1. 存量Flutter项目低成本接入鸿蒙生态
    纯Dart业务、纯Widget界面几乎不用改代码即可编译出鸿蒙HAP;只有带Android/iOS原生桥接的插件,才需要做鸿蒙适配替换。已经有成熟Flutter App,想快速覆盖鸿蒙设备,不用全部重写ArkTS。

  2. 多端UI高度一致性
    Flutter自绘渲染,不受各平台控件差异影响,手机、平板、车机界面表现统一;滚动、动画、首页各类动效(轮播、吸顶、骨架屏、入场动画)跨平台表现一致,和你前面问的App首页各种效果可以一套代码全部实现。

  3. 继承Flutter完整开发体验
    保留热重载、DevTools调试、完整Widget组件库;pub.dev海量纯Dart三方库直接复用,是鸿蒙跨端方案里三方库最丰富的方案。提供定制CLI,一条命令完成编译、真机调试、打包HAP。

  4. 可调用OpenHarmony原生系统能力
    支持调用分布式软总线、分布式数据KV、原子化服务、鸿蒙权限体系、硬件能力;Flutter页面和ArkTS原生页面可以混合开发、互相跳转,复杂原生逻辑继续写ArkTS,UI业务交给Flutter实现。

  5. 全场景设备覆盖
    支持OpenHarmony手机、平板、智慧屏、车机等设备,适合需要多终端统一UI的业务。引擎做了懒加载,跟随UIAbility生命周期启停,控制内存占用,减少后台资源消耗。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值