开源鸿蒙跨平台开发实战:Todo应用双端适配
本次的 UI 代码基于 KuiklyUI 的声明式 UI 开发,包含了布局组件、样式配置、数据绑定、事件绑定等核心知识点,同时兼顾了 UI 的美观性和交互性,双端运行时会自动适配 Android 和鸿蒙的原生组件,无需修改代码。本文总字数超万字,内容结构清晰、逻辑连贯,既包含基础的代码编写教学,也涵盖双端运行的环境配置、常见问题排查,同时还提供了项目扩展方向,帮助你在完成基础项目后进一步提升开发能
前言
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
在跨平台开发的浪潮中,OpenHarmony(开源鸿蒙)凭借其分布式能力、跨设备协同的特性,成为开发者关注的焦点。而 KuiklyUI 作为适配开源鸿蒙的轻量级跨平台 UI 框架,以“一次开发、多端运行”的优势,让开发者无需重复编写代码,就能实现 Android 和鸿蒙设备的应用适配。
很多入门开发者都会陷入“理论懂了,动手就废”的困境:看了很多跨平台开发的概念,却不知道从哪个项目入手,不清楚框架的实际使用流程,更不知道如何将代码落地到双端设备上运行。本文正是为解决这一痛点而生,以经典的 Todo 待办应用为开发案例,基于 KuiklyUI 框架展开全流程实战教学。
本文全程无冗余理论,所有步骤均为可落地的实操指南,从项目环境准备、代码编写到双端编译运行,每一步都配有详细的操作说明和代码示例。即使你是没有跨平台开发经验的新手,只要跟着步骤一步步操作,也能成功打造出一个能在 Android 和鸿蒙设备上同时运行的高性能 Todo 应用。
本文总字数超万字,内容结构清晰、逻辑连贯,既包含基础的代码编写教学,也涵盖双端运行的环境配置、常见问题排查,同时还提供了项目扩展方向,帮助你在完成基础项目后进一步提升开发能力,真正做到“学完就能用,用完就能拓展”。
1. 开发前必看:核心概念与环境准备
在开始实际开发前,我们需要先理清核心的概念,搭建好必备的开发环境,这是后续所有操作的基础,避免因概念模糊、环境缺失导致开发过程中出现不必要的问题。
1.1 核心概念解析
1.1.1 KuiklyUI 框架
KuiklyUI 是一款轻量级的跨平台 UI 框架,专为开源鸿蒙和 Android 双端适配设计,基于 Kotlin 语言开发,遵循“声明式 UI”的设计理念。开发者只需通过简洁的代码描述 UI 的结构和状态,框架会自动处理双端的原生组件映射,实现“一次编码,双端运行”。
KuiklyUI 的核心优势:
- 轻量高效:无冗余依赖,编译后的包体积小,运行时性能接近原生应用;
- 双端兼容:完美适配 Android 7.0+ 和开源鸿蒙 4.0+ 版本,无需针对不同平台修改核心代码;
- 声明式 UI:以函数式的方式编写 UI,代码结构清晰,易于维护和扩展;
- 响应式数据:内置可观察数据类型,数据变化时 UI 自动刷新,无需手动处理界面更新;
- 原生能力调用:支持直接调用 Android 和鸿蒙的原生 API,满足复杂的业务需求。
1.1.2 声明式 UI 与命令式 UI 的区别
传统的 Android 开发采用命令式 UI,需要开发者手动创建控件、设置属性、添加事件监听,当数据变化时,还需要手动更新控件的状态,代码繁琐且易出错。
KuiklyUI 采用声明式 UI,开发者只需描述“UI 应该是什么样子”,而不需要关注“如何实现 UI 的变化”。例如,我们只需绑定待办列表的数据,当列表添加、删除、修改数据时,UI 会自动同步刷新,无需手动调用刷新方法,大幅简化了 UI 开发的代码量。
1.1.3 跨平台开发的核心逻辑
本次开发的 Todo 应用,核心代码基于 Kotlin 编写,存放在commonMain目录下,这部分代码是 Android 和鸿蒙双端共用的,包括数据结构、业务逻辑、UI 布局;而针对双端的原生差异,框架会自动处理,开发者只需在对应的androidMain和ohosMain目录下做少量的原生配置,即可实现双端适配。
简单来说,跨平台开发的核心就是“抽离公共逻辑,适配平台差异”,而 KuiklyUI 已经帮我们封装了大部分平台差异,让我们可以将精力集中在核心业务开发上。
1.2 必备开发环境搭建
本次开发需要搭建 Android 和开源鸿蒙双端的开发环境,所有软件均为官方正版,可直接从官网下载,以下是详细的安装和配置步骤,Windows 和 macOS 系统均适用。
1.2.1 JDK 17 安装与配置
KuiklyUI 框架基于 Kotlin 1.9 开发,要求 JDK 版本为 17(推荐 OpenJDK 17),这是项目编译和运行的基础,必须优先安装。
- 下载地址:OpenJDK 17 官方下载,根据自己的系统选择对应的安装包(Windows 选 x64 Installer,macOS 选 x64 DMG);
- 安装步骤:双击安装包,按照默认步骤完成安装,无需修改安装路径;
- 环境变量配置:
- Windows:右键「此电脑」→「属性」→「高级系统设置」→「环境变量」,在「系统变量」中新建JAVA_HOME,值为 JDK 的安装路径(如 C:\Program Files\Java\jdk-17.0.9);在「Path」中添加 %JAVA_HOME%\bin;
- macOS:打开终端,执行 vim ~/.zshrc(若使用 bash 则执行 vim ~/.bash_profile),添加 export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.9.jdk/Contents/Home 和 export PATH=$JAVA_HOME/bin:$PATH,执行 source ~/.zshrc 使配置生效;
- 验证安装:打开终端/命令提示符,执行 java -version 和 javac -version,若显示 JDK 17 的版本信息,说明安装配置成功。
2. 项目初始化:下载并配置 KuiklyTodo 基础项目
完成开发环境搭建后,我们需要下载 KuiklyUI 官方提供的 KuiklyTodo 基础项目,这是我们本次开发的基础模板,包含了项目的目录结构、双端的配置文件和基础依赖,无需我们从零创建项目,大幅节省开发时间。
2.1 项目代码下载
本次项目提供两种下载方式,任选其一即可,推荐新手使用直接下载 ZIP 包的方式,操作更简单。
方式一:直接下载 ZIP 压缩包(推荐新手)
- 打开代码仓库:访问 AtomGit(https://atomgit.com/)或 GitCode(https://gitcode.net/),在搜索框中输入KuiklyTodo,点击搜索KuiklyTodo - AtomGit | GitCode
https://gitcode.com/Goway_Hui/KuiklyTodo/tree/main - 进入项目主页:选择官方的 KuiklyTodo 项目,进入项目详情页;
- 下载 ZIP 包:点击项目主页右上角的「下载 ZIP」按钮,等待项目压缩包下载完成;
- 注意:下载的压缩包名称一般为KuiklyTodo-main.zip,这是项目的主分支代码,包含最新的基础模板。
2.2 项目目录整理与解压
下载完成后,我们需要将项目压缩包解压到指定目录,并整理项目结构,方便后续开发操作。
- 新建项目根目录:在电脑上新建一个专门存放 Kuikly 项目的文件夹,建议命名为kuiklyTodoProjects,路径尽量简单,避免包含中文和特殊字符(如 Windows:E:\kuiklyTodoProjects;macOS:~/kuiklyTodoProjects);
- 解压项目:将下载的 KuiklyTodo-main.zip 压缩包解压到新建的根目录中,解压后会得到KuiklyTodo-main文件夹,这是我们的开发主目录。

2.3 项目核心目录结构解析
解压完成后,打开 KuiklyTodo-main 文件夹,我们需要先熟悉项目的核心目录结构,了解各个目录的作用,避免后续开发时找错文件位置。
项目采用多平台模块结构,核心目录分为demo、androidApp、ohosApp三大块,其中demo是双端共用的核心代码目录,androidApp和ohosApp分别是 Android 和鸿蒙端的原生配置目录,具体结构如下:
|
KuiklyTodo-main/ ├── demo/ # 双端共用核心代码目录(重点开发) │ ├── src/ │ │ ├── commonMain/ # 公共代码目录(Kotlin),包含数据、逻辑、UI(重点) │ │ │ ├── kotlin/ # Kotlin 核心代码,本次开发的所有代码都放在这里 │ │ │ └── resources/ # 公共资源(图片、字符串等) │ │ ├── androidMain/ # Android 端专属代码(少量配置,无需修改) │ │ └── ohosMain/ # 鸿蒙端专属代码(少量配置,无需修改) │ └── build.gradle.kts # demo 模块的编译配置(无需修改) ├── androidApp/ # Android 端原生配置目录(无需修改核心代码) │ ├── src/ # Android 原生代码和资源 │ └── build.gradle.kts # Android 端编译配置 ├── ohosApp/ # 鸿蒙端原生配置目录(无需修改核心代码) │ ├── src/ # 鸿蒙原生代码和资源 │ └── build.gradle.kts # 鸿蒙端编译配置 ├── build.gradle.kts # 项目根目录编译配置(无需修改) ├── settings.gradle.kts # 项目模块配置(无需修改) └── gradle/ # Gradle 依赖目录(无需修改) |
核心重点:本次开发的所有代码编写工作,均在demo/src/commonMain/kotlin目录下完成,其他目录仅需做少量配置,无需修改核心代码,这也是跨平台开发的核心优势。
在commonMain/kotlin目录下,官方已经为我们创建了 todo 业务目录,路径为:com/tencent/kuikly/demo/pages/todo,本次开发的三个核心文件(TodoItem.kt、TodoPage.kt、TodoPageUI.kt)都放在这个目录下,我们只需直接修改这三个文件即可。
2.4 用 Android Studio 打开项目
项目目录整理完成后,我们使用 Android Studio 打开项目,这是我们后续编写代码、编译 Android 端应用的主要工具。
- 打开 Android Studio,点击欢迎页的「Open an Existing Project」;
- 选择项目目录:在文件选择框中,找到解压后的KuiklyTodo-main文件夹,点击「OK」;
- 等待项目同步构建:第一次打开项目时,Android Studio 会自动下载项目所需的依赖包(如 KuiklyUI 框架、Kotlin 插件等),这个过程需要几分钟,具体时间取决于网络速度,必须等待同步完成后再进行后续开发;
- 同步完成标志:Android Studio 底部的「Build」面板显示「BUILD SUCCESSFUL」,且项目目录中没有红色报错,说明同步成功。
注意事项:
- 若同步过程中出现依赖下载失败,可检查网络是否正常,或点击「File」→「Sync Project with Gradle Files」重新同步;
- 若提示 Gradle 版本不兼容,可按照提示升级 Gradle 版本,Android Studio 会自动完成升级操作。

3. 数据层开发:定义 Todo 待办数据结构(TodoItem.kt)
开发一个应用,首先要定义数据结构,这是应用的“数据基石”。Todo 待办应用的核心数据是“待办事项”,我们需要为其定义一个清晰的数据结构,包含待办的唯一标识、内容、完成状态等核心属性,这部分代码写在TodoItem.kt文件中。
3.1 找到 TodoItem.kt 文件
按照以下路径,在 Android Studio 的项目目录中找到 TodoItem.kt 文件,这是我们第一个需要修改的文件:
|
demo/src/commonMain/kotlin/com/tencent/kuikly/demo/pages/todo/TodoItem.kt |
操作步骤:
- 在 Android Studio 左侧的「Project」面板中,展开 demo→src→commonMain→kotlin;
- 依次展开包名:com→tencent→kuikly→demo→pages→todo;
- 找到TodoItem.kt文件,双击打开。
3.2 编写 Todo 待办数据模型代码
打开 TodoItem.kt 文件后,将文件中原有的所有代码全部删除,替换为以下完整的 Kotlin 代码,代码中包含详细的注释,解释每一个属性和关键字的作用。
完整代码示例
|
package com.tencent.kuikly.demo.pages.todo /** * 待办事项数据模型 * @param id 唯一标识 * @param content 待办内容 * @param isCompleted 是否完成(默认未完成) */ data class TodoItem( val id: Long, var content: String, var isCompleted: Boolean = false ) |
3.3 核心代码详细解析
以上代码虽然简短,但包含了 Kotlin 数据类的核心知识点,也是跨平台开发中数据层的基础写法,我们逐一解析,帮助大家理解背后的逻辑。
3.3.1 package 包名声明
代码第一行 package com.tencent.kuikly.demo.pages.todo 是包名声明,必须与文件所在的目录路径一致,否则会出现编译错误。包名的作用是区分不同的代码模块,避免类名冲突,这是 Kotlin/Java 开发的基本规范。
3.3.2 data class 数据类
关键字 data class 表示这是一个数据类,Kotlin 中的数据类是专门用来存储数据的类,框架会自动为其生成一系列常用的方法,如 equals()、hashCode()、toString()、copy() 等,无需我们手动编写,大幅简化了代码量。
在 Todo 应用中,TodoItem 仅用于存储待办事项的数据,没有复杂的业务逻辑,因此使用数据类是最合适的选择。注意:数据类必须至少包含一个主构造函数的参数,否则会编译报错。
3.3.3 核心属性定义
我们为 TodoItem 定义了三个核心属性,覆盖了待办事项的所有必要信息,属性的类型和修饰符都经过精心设计:
- id: Long:
- 类型为 Long,而非 Int,因为 Long 的取值范围更大,避免待办事项数量过多时出现 ID 重复;
- 使用 val 修饰,代表只读属性,ID 是待办事项的唯一标识,一旦创建就不能修改,保证数据的唯一性;
- content: String:
- 类型为 String,用于存储待办的文字内容;
- 使用 var 修饰,代表可变属性,支持后续编辑待办内容(为项目扩展预留接口);
- isCompleted: Boolean = false:
- 类型为 Boolean,用于标记待办是否完成;
- 使用 var 修饰,支持切换完成状态;
- 设置默认值为 false,代表新建的待办事项默认是未完成状态,符合用户的使用习惯。
3.3.4 注释规范
代码中添加了详细的文档注释(/** */),注释中说明的类的作用、每个参数的含义和类型,这是专业开发的必备规范。良好的注释可以让其他开发者快速理解代码的含义,也方便自己后续维护项目,建议大家在开发中养成写注释的习惯。
3.4 代码格式检查与保存
编写完代码后,我们需要对代码进行格式化,保证代码的可读性,然后保存文件。
- 格式化代码:使用快捷键Ctrl+Alt+L(Windows)/Cmd+Opt+L(macOS),Android Studio 会自动按照 Kotlin 的编码规范格式化代码;
- 保存文件:使用快捷键Ctrl+S(Windows)/Cmd+S(macOS)保存文件;
- 检查报错:确保文件中没有红色的波浪线报错,若有报错,检查代码是否有拼写错误、包名是否正确。
至此,数据层开发完成,我们已经定义了 Todo 待办事项的核心数据结构,后续的业务逻辑和 UI 界面都会基于这个数据模型展开。

4. 逻辑层开发:编写 Todo 应用核心业务逻辑(TodoPage.kt)
如果说数据层是应用的“数据基石”,那么逻辑层就是应用的“大脑”,负责处理应用的所有核心业务逻辑,包括待办事项的添加、删除、状态切换、数量统计等。本次开发的逻辑层代码写在TodoPage.kt文件中,该文件是 Todo 应用的逻辑控制器,继承自 KuiklyUI 的 KuiklyPage 类,实现了所有业务逻辑的封装。
4.1 找到 TodoPage.kt 文件
TodoPage.kt 与 TodoItem.kt 在同一个目录下,路径如下:
|
demo/src/commonMain/kotlin/com/tencent/kuikly/demo/pages/todo/TodoPage.kt |
操作步骤:在 Android Studio 的 todo 目录下,找到TodoPage.kt文件,双击打开即可。
4.2 编写核心业务逻辑代码
打开 TodoPage.kt 文件后,删除原有所有代码,替换为以下完整的业务逻辑代码,代码包含详细的注释,同时遵循 Kotlin 的编码规范,结构清晰、逻辑连贯。
完整代码示例
|
/** * @ProjectName : KuiklyUI * @Author : GuoJiaHui * @Time : 2026年01月29日 17:30 PM * @Description : 待办事项页面逻辑控制器 * 负责管理待办事项列表的数据状态、增删改查操作 */ package com.tencent.kuikly.demo.pages.todo import com.tencent.kuikly.core.KuiklyPage import com.tencent.kuikly.core.observable import com.tencent.kuikly.core.observableList class TodoPage : KuiklyPage() { // 待办列表(响应式,数据变化自动刷新界面) val todoList = observableList<TodoItem>() // 输入框内容(双向绑定) val inputText = observable("") // 自增 ID,保证每条待办的唯一性 private var autoId = 0L /** * 添加新的待办事项 */ fun addTodo() { val content = inputText.value.trim() if (content.isEmpty()) return todoList.add( TodoItem( id = autoId++, content = content ) ) inputText.value = "" } /** * 切换待办的完成状态 */ fun toggleTodo(item: TodoItem) { val index = todoList.indexOf(item) if (index != -1) { todoList[index] = item.copy(isCompleted = !item.isCompleted) } } /** * 删除指定待办 */ fun deleteTodo(item: TodoItem) { todoList.remove(item) } /** * 清空所有已完成的待办 */ fun clearCompleted() { todoList.removeAll { it.isCompleted } } /** * 统计未完成的待办数量 */ fun getUndoneCount(): Int { return todoList.count { !it.isCompleted } } } |

4.3 核心代码与知识点详细解析
TodoPage.kt 的代码是本次开发的核心,包含了 KuiklyUI 框架的核心特性(可观察数据)、Kotlin 的核心语法(类、方法、lambda 表达式)以及跨平台开发的逻辑与视图分离思想,我们从核心特性、业务方法、关键知识点三个方面进行详细解析。
4.3.1 KuiklyUI 核心特性:可观察数据(observable/observableList)
可观察数据是 KuiklyUI 框架的核心特性,也是实现“数据变化,UI 自动刷新”的关键,本次开发使用了两种可观察数据类型:observable(可观察变量)和observableList(可观察列表),这是跨平台声明式 UI 开发的基础。
- observableList():
- 作用:用于存储待办事项列表,是 KuiklyUI 对普通 List 的封装;
- 核心特性:当列表执行add、remove、set等操作时,框架会自动检测到数据变化,并通知 UI 进行刷新,无需我们手动调用刷新方法;
- 注意事项:observableList 仅监听列表本身的变化(增删改元素),不监听元素对象属性的变化。例如,直接修改 todoItem.isCompleted = true,列表不会检测到变化,UI 也不会刷新,因此我们在 toggleTodo 方法中使用了 copy 方法创建新对象替换原对象。
- observable(""):
- 作用:用于绑定 UI 输入框的内容,是 KuiklyUI 对普通变量的封装;
- 核心特性:支持双向绑定,即 UI 输入框的内容变化时,observable 变量的 value 属性会同步变化;当我们修改 observable 变量的 value 属性时,UI 输入框的内容也会同步刷新;
- 使用方式:通过 .value 获取或修改变量的值,如 inputText.value.trim()(获取值)、inputText.value = ""(修改值)。
可观察数据的优势:彻底摆脱了命令式 UI 中“手动更新 UI”的繁琐操作,让开发者可以将精力集中在业务逻辑上,而不是 UI 刷新的细节上,大幅提升开发效率,同时减少因手动刷新导致的 Bug。
4.3.2 核心业务方法解析
本次开发实现了 5 个核心业务方法,覆盖了 Todo 应用的所有基础功能,每个方法都遵循“单一职责”原则,一个方法只处理一个业务逻辑,代码易于理解和维护,同时为后续扩展预留了接口。
- addTodo():添加待办事项
- 核心逻辑:获取输入框内容→内容校验→生成新待办对象→添加到列表→清空输入框;
- 关键细节:使用 trim() 去除首尾空格,避免添加空待办;使用自增 ID 保证唯一性;添加完成后清空输入框,提升用户体验。
- toggleTodo(item: TodoItem):切换待办状态
- 核心逻辑:找到待办索引→校验索引→创建新对象(修改状态)→替换原对象;
- 关键细节:使用数据类的 copy 方法创建新对象,因为 observableList 不监听对象属性的修改,必须替换对象才能触发 UI 刷新。
- deleteTodo(item: TodoItem):删除待办事项
- 核心逻辑:直接从列表中移除指定待办对象;
- 关键细节:利用 observableList 的特性,移除后 UI 自动刷新,无需额外操作。
- clearCompleted():清空已完成待办
- 核心逻辑:使用 removeAll 方法,根据过滤条件移除所有已完成的待办;
- 关键细节:使用 lambda 表达式作为过滤条件,代码简洁高效,符合 Kotlin 的编码风格。
- getUndoneCount():统计未完成待办数量
- 核心逻辑:使用 count 方法,根据过滤条件统计未完成的待办数量;
- 关键细节:返回 Int 类型,供 UI 层绑定显示,数据变化时 UI 自动更新统计数字。
5. 视图层开发:打造高颜值可交互 UI 界面(TodoPageUI.kt)
视图层是应用的“脸面”,负责展示 UI 界面、接收用户的操作(如点击、输入、勾选),并将用户操作传递给逻辑层,由逻辑层处理业务逻辑。本次开发的视图层基于 KuiklyUI 的声明式 UI开发,代码写在TodoPageUI.kt文件中,通过函数式的方式编写 UI 布局,实现与逻辑层的无缝绑定,同时保证 Android 和鸿蒙双端的 UI 样式一致。
5.1 找到 TodoPageUI.kt 文件
TodoPageUI.kt 与前两个文件在同一目录下,路径如下:
|
demo/src/commonMain/kotlin/com/tencent/kuikly/demo/pages/todo/TodoPageUI.kt |
操作步骤:在 Android Studio 的 todo 目录下,找到TodoPageUI.kt文件,双击打开。
5.2 编写声明式 UI 代码
打开 TodoPageUI.kt 文件后,删除原有所有代码,替换为以下完整的 UI 代码。代码采用 KuiklyUI 的声明式 UI 写法,结构分为整体页面布局和单条待办项布局两部分,包含详细的注释,同时做了基础的样式美化,兼顾美观性和交互性,双端运行时会自动适配原生组件。
完整代码示例
|
/** * @ProjectName : KuiklyUI * @Author : GuoJiaHui * @Time : 2026年01月29日 17:30 PM * @Description : 待办事项页面UI构建逻辑 * 包含整体布局、样式定义及事件绑定 */ package com.tencent.kuikly.demo.pages.todo import com.tencent.kuikly.core.* import com.tencent.kuikly.core.extensions.* fun TodoPage.pageView() = column { // 顶部标题 text("Todo 待办清单") { textSize(24) textBold() margin(20) centerHorizontal() } // 统计栏:未完成数量 + 清空按钮 row { text("未完成:") { textSize(14) marginLeft(20) } text { textSize(14) textColor(0xFFFF5722) bindText { page.getUndoneCount().toString() } } space(weight = 1f) button("清空已完成") { marginRight(20) onClick { page.clearCompleted() } } } // 待办列表 list { items(page.todoList) { item -> todoItem(item) } }.weight(1f) // 底部输入栏 row { input { hint("请输入待办事项") weight(1f) margin(10) bindText(page.inputText) } button("添加") { marginRight(10) onClick { page.addTodo() } } } } /** * 单条待办项的UI布局 */ fun ViewScope.todoItem(item: TodoItem) { row { checkBox { checked(item.isCompleted) onCheckedChange { page.toggleTodo(item) } margin(10) } text(item.content) { textSize(16) marginVertical(14) if (item.isCompleted) { textColor(0xFF999999) strikeThrough() } else { textColor(0xFF333333) } } space(weight = 1f) image { res("ic_delete") size(24) margin(10) onClick { page.deleteTodo(item) } } onClick { page.toggleTodo(item) } onLongClick { page.deleteTodo(item) true } } divider() } |

5.3 核心 UI 代码与知识点详细解析
本次的 UI 代码基于 KuiklyUI 的声明式 UI 开发,包含了布局组件、样式配置、数据绑定、事件绑定等核心知识点,同时兼顾了 UI 的美观性和交互性,双端运行时会自动适配 Android 和鸿蒙的原生组件,无需修改代码。我们从核心布局组件、数据绑定、事件绑定、样式美化、跨平台 UI 适配五个方面进行详细解析。
5.3.1 KuiklyUI 核心布局组件
KuiklyUI 提供了丰富的原生布局组件,本次开发使用了column、row、list三个核心布局组件,这也是声明式 UI 开发中最常用的布局组件,通过组合这三个组件,可以实现绝大多数的 UI 布局。
- column:垂直布局组件
- 作用:将子组件从上到下垂直排列,本次用于整体页面的布局,包含标题、统计栏、列表、输入栏;
- 核心属性:width(宽度)、height(高度)、padding(内边距)、margin(外边距)、weight(权重);
- 关键配置:MatchParent 表示匹配父容器的宽度/高度,wrapContent 表示自适应子组件的宽度/高度。
- row:水平布局组件
- 作用:将子组件从左到右水平排列,本次用于统计栏、输入栏、单条待办项的布局;
- 核心属性:与 column 一致,weight 属性用于分配剩余空间,如 space(weight=1f) 占满中间剩余空间,将按钮推到最右侧;
- 优势:通过 weight 可以轻松实现“左侧占满,右侧固定”或“平分空间”的布局,无需手动计算宽度。
- list:列表组件
- 作用:用于渲染动态列表,本次用于渲染待办事项列表,自动绑定逻辑层的 todoList;
- 核心特性:items(page.todoList) 将列表与可观察列表绑定,数据变化时列表自动刷新;
- 关键配置:weight=1f 让列表占满中间剩余空间,自适应屏幕高度,避免列表超出屏幕或出现空白。
此外,还使用了 space(空白占位符)、divider(分割线)等辅助组件,提升 UI 的层次感和美观度
5.4 代码检查与保存
编写完 UI 代码后,按照以下步骤检查并保存文件,确保代码无错误:
- 格式化代码:使用快捷键Ctrl+Alt+L(Windows)/Cmd+Opt+L(macOS)格式化代码,保证代码结构清晰;
- 检查报错:确保文件中没有红色波浪线报错,重点检查导入类、组件名、样式属性是否有拼写错误;
- 保存文件:使用快捷键Ctrl+S(Windows)/Cmd+S(macOS)保存文件;
- 初步编译:点击 Android Studio 顶部的「Build」→「Make Project」,编译整个项目,若显示「BUILD SUCCESSFUL」,说明视图层代码无编译错误。
至此,视图层开发完成,我们已经打造了一个高颜值、可交互的 Todo 应用 UI 界面,同时实现了与逻辑层的无缝绑定,接下来只需将应用编译并运行到 Android 和鸿蒙设备上,即可验证应用的功能。
6. 双端运行实战:Android 端编译与安装
完成代码开发后,我们首先将应用编译并运行到 Android 设备上,验证应用的功能和交互效果。Android 端的编译和运行主要通过 Android Studio 完成,操作步骤清晰,适合新手入门。
6.1 准备 Android 运行环境
在运行应用前,需要准备好 Android 运行环境,包括模拟器或真机设备:
- 模拟器:Android Studio 自带模拟器,适合没有真机设备的开发者;
- 真机设备:推荐使用真机设备,运行效果更接近实际使用场景,调试更方便。
6.1.1 配置 Android 模拟器(可选)
- 打开 Android Studio,点击顶部菜单栏「Tools」→「Device Manager」;
- 点击「Create device」,选择一款手机设备(如 Pixel 7),点击「Next」;
- 选择系统镜像(推荐 Android 13 及以上版本),点击「Next」;
- 配置模拟器名称,点击「Finish」,完成模拟器创建;
- 点击「Run」按钮,启动模拟器,等待模拟器启动完成。
6.1.2 配置 Android 真机设备(推荐)
- 打开手机「设置」→「关于手机」,连续点击「版本号」7 次,开启「开发者选项」;
- 进入「开发者选项」,开启「USB 调试」;
- 使用 USB 数据线将手机与电脑连接,手机弹出「允许 USB 调试」提示时,选择「允许」;
- 在 Android Studio 顶部的设备选择栏中,选择连接的真机设备。
6.2 编译并运行 Android 应用
- 在 Android Studio 顶部的设备选择栏中,选择要运行的设备(模拟器或真机);
- 点击顶部菜单栏「Run」→「Run 'androidApp'」,或直接点击绿色的「Run」按钮;
- 等待编译完成:Android Studio 会自动编译项目,并将应用安装到设备上,这个过程需要几分钟,具体时间取决于设备性能;
- 验证应用运行:应用安装完成后,会自动启动,在设备上打开「KuiklyTodo」应用,即可看到我们开发的 Todo 待办清单界面。
6.3 验证应用功能
在 Android 设备上运行应用后,我们需要验证应用的所有功能是否正常:
- 添加待办:在输入框中输入待办内容,点击「添加」按钮或按回车键,验证待办是否成功添加到列表中;
- 切换完成状态:点击待办项的勾选框或待办项的任意位置,验证待办状态是否切换,已完成的待办是否显示为浅灰色并带有中划线;
- 删除待办:点击待办项的删除按钮或长按待办项,验证待办是否成功从列表中移除;
- 清空已完成:点击「清空已完成」按钮,验证所有已完成的待办是否被清空;
- 统计未完成数量:添加、删除、切换待办状态,验证未完成数量是否实时更新。
如果所有功能都正常运行,说明 Android 端的开发和编译没有问题,接下来我们将应用编译并运行到鸿蒙设备上。



7. 双端运行实战:开源鸿蒙端编译与部署
鸿蒙端的编译和部署主要通过 DevEco Studio 完成,操作步骤与 Android 端类似,但需要注意鸿蒙项目的配置和签名问题。本节将详细介绍鸿蒙端的编译、部署和验证过程。
7.1 用 DevEco Studio 打开项目
- 打开 DevEco Studio,点击欢迎页的「Open an Existing Project」;
- 选择项目目录:在文件选择框中,找到我们的项目根目录(KuiklyTodo-main),点击「OK」;
- 等待项目同步构建:第一次打开项目时,DevEco Studio 会自动下载项目所需的依赖包,这个过程需要几分钟,具体时间取决于网络速度,必须等待同步完成后再进行后续操作;
- 同步完成标志:DevEco Studio 底部的「Build」面板显示「BUILD SUCCESSFUL」,且项目目录中没有红色报错,说明同步成功。
7.2 配置鸿蒙项目签名(必做)
在部署应用到鸿蒙设备前,必须配置项目签名,否则无法安装应用。DevEco Studio 提供了自动签名功能,操作步骤如下:
- 打开 DevEco Studio,点击顶部菜单栏「File」→「Project Structure」;
- 选择「Modules」→「ohosApp」→「Signing Configs」;
- 点击「+」按钮,创建新的签名配置;
- 输入签名配置名称(如 debug),点击「OK」;
- 点击「Generate」按钮,生成签名文件,按照提示填写签名信息(别名、密码等);
- 点击「OK」,完成签名配置;
- 点击「Apply」→「OK」,保存签名配置。
7.3 准备鸿蒙运行环境
鸿蒙端的运行环境包括模拟器和真机设备,操作步骤如下:
7.3.1 配置鸿蒙模拟器(可选)
- 打开 DevEco Studio,点击顶部菜单栏「Tools」→「Device Manager」;
- 点击「Create device」,选择一款鸿蒙设备(如 Huawei Mate 60),点击「Next」;
- 选择系统镜像(推荐开源鸿蒙 4.0 及以上版本),点击「Next」;
- 配置模拟器名称,点击「Finish」,完成模拟器创建;
- 点击「Run」按钮,启动模拟器,等待模拟器启动完成。
7.3.2 配置鸿蒙真机设备(推荐)
- 打开鸿蒙设备「设置」→「关于手机」,连续点击「版本号」7 次,开启「开发者选项」;
- 进入「开发者选项」,开启「USB 调试」和「允许调试应用」;
- 使用 USB 数据线将设备与电脑连接,设备弹出「允许 USB 调试」提示时,选择「允许」;
- 在 DevEco Studio 顶部的设备选择栏中,选择连接的真机设备。
7.4 编译并部署鸿蒙应用
- 在 DevEco Studio 顶部的设备选择栏中,选择要运行的设备(模拟器或真机);
- 点击顶部菜单栏「Run」→「Run 'ohosApp'」,或直接点击绿色的「Run」按钮;
- 等待编译完成:DevEco Studio 会自动编译项目,并将应用安装到设备上,这个过程需要几分钟,具体时间取决于设备性能;
- 验证应用运行:应用安装完成后,会自动启动,在设备上打开「KuiklyTodo」应用,即可看到我们开发的 Todo 待办清单界面。
7.5 验证应用功能
在鸿蒙设备上运行应用后,我们需要验证应用的所有功能是否正常,验证步骤与 Android 端一致:
- 添加待办:在输入框中输入待办内容,点击「添加」按钮或按回车键,验证待办是否成功添加到列表中;
- 切换完成状态:点击待办项的勾选框或待办项的任意位置,验证待办状态是否切换,已完成的待办是否显示为浅灰色并带有中划线;
- 删除待办:点击待办项的删除按钮或长按待办项,验证待办是否成功从列表中移除;
- 清空已完成:点击「清空已完成」按钮,验证所有已完成的待办是否被清空;
- 统计未完成数量:添加、删除、切换待办状态,验证未完成数量是否实时更新。
如果所有功能都正常运行,说明鸿蒙端的开发和编译没有问题,我们已经成功打造了一个能在 Android 和鸿蒙双端同时运行的高性能 Todo 应用。
8. 精细化调试:双端常见问题排查与解决
在双端开发和运行过程中,难免会遇到各种问题,如编译失败、应用闪退、功能异常等。本节将总结双端开发中常见的 10 大问题,并提供详细的排查步骤和解决方案,帮助大家快速定位并解决问题。
8.1 常见问题 1:项目同步失败,依赖下载失败
问题描述:打开项目时,Android Studio/DevEco Studio 提示依赖下载失败,项目同步失败。
排查步骤:
- 检查网络连接是否正常,尝试切换网络(如从 Wi-Fi 切换到移动热点);
- 检查 Gradle 版本是否与项目兼容,若提示 Gradle 版本不兼容,按照提示升级 Gradle 版本;
- 清理项目缓存:点击「File」→「Invalidate Caches / Restart」,选择「Invalidate and Restart」,重启开发工具;
- 手动下载依赖:若依赖下载失败,可手动下载对应的依赖包,放到项目的 gradle/wrapper/dists 目录下。
8.2 常见问题 2:编译失败,提示“找不到符号”
问题描述:编译项目时,提示“找不到符号”,如找不到 TodoItem、TodoPage 等类。
排查步骤:
- 检查包名是否正确,确保文件所在的目录路径与包名声明一致;
- 检查导入类是否正确,确保导入了需要的类和包;
- 检查类名和方法名是否拼写正确,区分大小写;
- 清理项目并重新编译:点击「Build」→「Clean Project」,然后点击「Build」→「Rebuild Project」。
8.3 常见问题 3:应用闪退,提示“空指针异常”
问题描述:应用启动后闪退,日志中提示“空指针异常”(NullPointerException)。
排查步骤:
- 检查代码中是否有未初始化的变量,确保所有变量在使用前都已赋值;
- 检查可观察数据的使用是否正确,确保 observable 和 observableList 变量在使用前都已初始化;
- 检查参数传递是否正确,确保传递的参数不为空;
- 查看日志定位问题:在 Android Studio/DevEco Studio 的「Logcat」面板中,查看闪退时的日志,定位空指针异常的位置。
8.4 常见问题 4:UI 不刷新,数据变化后 UI 无变化
问题描述:修改待办状态、添加/删除待办后,UI 没有实时刷新,数据与 UI 不一致。
排查步骤:
- 检查是否使用了 KuiklyUI 的可观察数据(observable/observableList),确保数据变化时能触发 UI 刷新;
- 检查是否直接修改了对象属性,而没有替换对象:对于 observableList,修改对象属性不会触发 UI 刷新,需要使用 copy 方法创建新对象替换原对象;
- 检查数据绑定是否正确,确保 UI 组件与可观察数据正确绑定;
- 重启应用:若以上步骤都无法解决问题,尝试重启应用。
8.5 常见问题 5:Android 端应用无法安装到真机设备
问题描述:编译 Android 应用后,无法安装到真机设备,提示“安装失败”。
排查步骤:
- 检查手机是否开启了「USB 调试」,确保手机与电脑正常连接;
- 检查应用签名是否正确,若使用了自定义签名,确保签名文件和密码正确;
- 检查手机存储空间是否充足,若存储空间不足,清理手机存储空间;
- 卸载旧版本应用:若手机上已安装旧版本的应用,先卸载旧版本,再安装新版本。
8.6 常见问题 6:鸿蒙端应用无法部署到真机设备
问题描述:编译鸿蒙应用后,无法部署到真机设备,提示“部署失败”。
排查步骤:
- 检查设备是否开启了「USB 调试」和「允许调试应用」,确保设备与电脑正常连接;
- 检查项目签名是否配置正确,确保签名文件和密码正确;
- 检查设备是否支持应用的最低 API 版本,若设备 API 版本过低,升级设备系统;
- 重启设备和开发工具:若以上步骤都无法解决问题,尝试重启设备和 DevEco Studio。
8.7 常见问题 7:输入框内容无法清空,添加待办后输入框仍有内容
问题描述:添加待办后,输入框内容没有清空,需要手动删除。
排查步骤:
- 检查 addTodo() 方法中是否正确清空了 inputText.value,确保代码为 inputText.value = "";
- 检查数据绑定是否正确,确保输入框与 inputText 变量正确绑定;
- 检查是否有其他代码修改了 inputText.value,导致输入框内容无法清空;
- 重启应用:若以上步骤都无法解决问题,尝试重启应用。
8.8 常见问题 8:待办项点击无响应,无法切换完成状态
问题描述:点击待办项的勾选框或待办项的任意位置,待办状态没有切换,UI 无变化。
排查步骤:
- 检查 toggleTodo() 方法是否正确实现,确保代码能正确找到待办项的索引并替换对象;
- 检查事件绑定是否正确,确保勾选框和待办项的点击事件正确绑定到 toggleTodo() 方法;
- 检查 todoList 是否为 observableList,确保数据变化时能触发 UI 刷新;
- 查看日志定位问题:在「Logcat」面板中,查看点击时的日志,定位问题所在。
8.9 常见问题 9:删除按钮点击无响应,无法删除待办
问题描述:点击待办项的删除按钮,待办没有从列表中移除,UI 无变化。
排查步骤:
- 检查 deleteTodo() 方法是否正确实现,确保代码能正确从 todoList 中移除待办项;
- 检查事件绑定是否正确,确保删除按钮的点击事件正确绑定到 deleteTodo() 方法;
- 检查 todoList 是否为 observableList,确保数据变化时能触发 UI 刷新;
- 查看日志定位问题:在「Logcat」面板中,查看点击时的日志,定位问题所在。
8.10 常见问题 10:未完成数量统计错误,数量与实际待办状态不一致
问题描述:添加、删除、切换待办状态后,未完成数量统计错误,与实际待办状态不一致。
排查步骤:
- 检查 getUndoneCount() 方法是否正确实现,确保代码能正确统计未完成的待办数量;
- 检查数据绑定是否正确,确保未完成数量的文字与 getUndoneCount() 方法正确绑定;
- 检查 todoList 是否为 observableList,确保数据变化时能触发 UI 刷新;
- 重启应用:若以上步骤都无法解决问题,尝试重启应用。
9. 项目性能优化:让应用更流畅、更稳定
完成基础功能开发后,我们可以对项目进行性能优化,提升应用的流畅度和稳定性。本节将从代码优化、资源优化、内存优化三个方面,介绍 KuiklyUI 应用的性能优化技巧。
9.1 代码优化:提升代码执行效率
- 避免不必要的对象创建:在循环和频繁调用的方法中,避免创建大量临时对象,减少内存分配和垃圾回收的开销;
- 使用懒加载:对于不常用的对象和资源,使用懒加载(by lazy),在需要时才初始化,减少启动时间和内存占用;
- 优化列表渲染:对于长列表,使用 list 组件的 key 属性,指定列表项的唯一标识,提升列表渲染效率;
- 减少 UI 刷新次数:避免频繁修改可观察数据,批量更新数据,减少 UI 刷新次数,提升应用流畅度。
9.2 资源优化:减小应用包体积
- 压缩图片资源:使用图片压缩工具(如 TinyPNG)压缩图片资源,减小图片大小,减少应用包体积;
- 移除无用资源:删除项目中未使用的资源文件(如图片、字符串、布局文件),减小应用包体积;
- 使用矢量图:优先使用矢量图(SVG),矢量图可以无损缩放,且体积更小;
- 开启资源混淆:在编译时开启资源混淆,移除未使用的资源,减小应用包体积。
9.3 内存优化:减少内存占用
- 及时释放资源:在页面销毁时,及时释放占用的资源(如图片、数据库连接、网络请求),避免内存泄漏;
- 使用弱引用:对于不需要强引用的对象,使用弱引用(WeakReference),避免对象无法被回收,导致内存泄漏;
- 优化数据存储:对于大量数据,使用分页加载和缓存机制,避免一次性加载大量数据,占用过多内存;
- 监控内存使用:使用 Android Studio/DevEco Studio 的内存分析工具,监控应用的内存使用情况,定位内存泄漏问题。
10. 项目进阶扩展:从基础 Todo 到多功能待办应用
完成基础 Todo 应用开发后,我们可以对项目进行进阶扩展,添加更多功能,让应用更加实用。本节将介绍几个常见的扩展方向,帮助大家进一步提升开发能力。
10.1 扩展方向 1:添加待办分类功能
- 功能描述:为待办事项添加分类(如工作、生活、学习),用户可以按分类筛选待办事项;
- 实现思路:
- 在 TodoItem 数据类中添加 category 属性,存储待办分类;
- 在 UI 中添加分类选择组件(如下拉菜单、标签页),用户可以选择待办分类;
- 在逻辑层添加分类筛选方法,根据分类筛选待办事项;
- 在 UI 中绑定分类筛选结果,实现按分类展示待办事项。
10.2 扩展方向 2:添加待办优先级和截止时间功能
- 功能描述:为待办事项添加优先级(高、中、低)和截止时间,用户可以按优先级和截止时间排序待办事项;
- 实现思路:
- 在 TodoItem 数据类中添加 priority 和 deadline 属性,存储待办优先级和截止时间;
- 在 UI 中添加优先级选择和截止时间选择组件;
- 在逻辑层添加排序方法,根据优先级和截止时间排序待办事项;
- 在 UI 中绑定排序结果,实现按优先级和截止时间展示待办事项。
10.3 扩展方向 3:添加数据持久化功能
- 功能描述:将待办事项存储到本地数据库中,应用重启后待办事项不会丢失;
- 实现思路:
- 集成本地数据库框架(如 Room、SQLite),创建待办事项表;
-
- 在逻辑层添加数据库操作方法(增、删、改、查);
- 在应用启动时,从数据库中加载待办事项,初始化 todoList;
-
- 在添加、删除、切换待办状态时,同步更新数据库中的数据。
10.4 扩展方向 4:添加待办提醒功能
- 功能描述:为待办事项设置提醒时间,到时间后应用会发送通知提醒用户;
- 实现思路:
- 集成鸿蒙/Android 的通知 API,创建通知通道;
- 在 TodoItem 数据类中添加 reminderTime 属性,存储提醒时间;
- 在逻辑层添加提醒设置方法,设置待办事项的提醒时间;
- 使用 AlarmManager 或 WorkManager 实现定时提醒,到时间后发送通知。
10.5 扩展方向 5:添加多端数据同步功能
- 功能描述:将待办事项同步到云端,实现多端数据同步(如手机、平板、电脑);
- 实现思路:
- 集成云服务(如 Firebase、华为云),创建待办事项云数据库;
- 在逻辑层添加云同步方法,将本地数据同步到云端,或从云端同步数据到本地;
- 添加登录功能,用户登录后可以同步自己的待办事项;
- 实现增量同步,只同步变化的数据,提升同步效率。
11. 总结与后续学习方向
通过本文的实战教程,我们从零开始,基于 KuiklyUI 框架打造了一个能在 Android 和鸿蒙双端同时运行的高性能 Todo 应用。从项目初始化、数据层开发、逻辑层开发、视图层开发,到双端编译运行、问题排查和性能优化,我们完整地走完了跨平台应用开发的全流程。
11.1 核心收获
- 掌握 KuiklyUI 框架核心特性:理解了声明式 UI、可观察数据、逻辑与视图分离等核心概念,掌握了 KuiklyUI 框架的使用方法;
- 熟悉跨平台开发流程:了解了跨平台应用开发的全流程,从项目初始化到双端编译运行,掌握了常见问题的排查和解决方法;
- 提升 Kotlin 编程能力:通过编写数据类、业务逻辑和 UI 代码,提升了 Kotlin 编程能力,熟悉了 Kotlin 的核心语法和编码规范;
- 具备实战开发能力:能够独立开发简单的跨平台应用,并对项目进行性能优化和功能扩展。
11.2 后续学习方向
- 深入学习 KuiklyUI 框架:学习 KuiklyUI 框架的高级特性,如状态管理、路由导航、原生能力调用等,提升框架使用能力;
- 学习开源鸿蒙开发:深入学习开源鸿蒙的核心技术,如分布式能力、ArkTS 语言、鸿蒙原生 API 等,掌握鸿蒙应用开发的核心能力;
- 学习跨平台开发框架:除了 KuiklyUI,还可以学习其他跨平台开发框架(如 Flutter、React Native),对比不同框架的优缺点,选择适合自己的开发框架;
- 参与开源项目:参与 KuiklyUI 或开源鸿蒙的开源项目,贡献代码,提升自己的开发能力和社区影响力;
- 持续实践:通过开发更多的跨平台应用,不断积累实战经验,提升自己的开发水平。
结语
跨平台开发是未来移动应用开发的趋势,而 KuiklyUI 框架为开源鸿蒙和 Android 双端开发提供了便捷的解决方案。希望本文的实战教程能帮助大家快速入门 KuiklyUI 开发,打造出更多优秀的跨平台应用。
如果你在开发过程中遇到问题,欢迎查阅 KuiklyUI 官方文档或在社区中提问,也可以参考本文的问题排查部分,快速定位并解决问题。最后,祝大家在跨平台开发的道路上越走越远,不断提升自己的开发能力!
更多推荐





所有评论(0)