运动记录与热量消耗分析 - Kotlin KMP鸿蒙工具

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
使用 Kotlin Multiplatform + Kotlin/JS,将运动记录分析逻辑导出为 JavaScript,并在 OpenHarmony ArkTS 页面中调用,实现一个简单的运动与热量评估小工具。
1. 案例简介
本案例聚焦在“日常运动”和“热量消耗”的场景:
- 在 Kotlin 中实现
exerciseCaloriesAnalyzer函数,接收一串运动时长记录(单位:分钟),例如30 20 15 10; - 统计总运动时长、单次平均时长、最长/最短运动时间;
- 基于一个简单的 MET 模型估算总消耗热量;
- 对运动结构(短时/中等/较长)给出基础分析,并输出整体建议;
- 在 ArkTS 页面
Index.ets中通过输入框和按钮进行交互,一键查看当天运动的“量”和“大致消耗”。
这个案例和“饮水记录与补水分析工具”“睡眠质量评分工具”一起,构成了一个较完整的生活健康类小组件集合,展示了如何用一份 Kotlin 业务逻辑支撑多个不同维度的健康评估。
2. Kotlin 实现:exerciseCaloriesAnalyzer
Kotlin 源码位于 src/jsMain/kotlin/App.kt,通过 @JsExport 导出。输入格式如下:
- 一行字符串,例如:
30 20 15 10; - 每个数字代表一次运动的时长,单位为“分钟”;
- 可以自由增加或减少记录次数,例如
45 30、10 10 10 10 10等。
核心实现节选如下(只展示主要逻辑):
@OptIn(ExperimentalJsExport::class)
@JsExport
fun exerciseCaloriesAnalyzer(inputText: String = "30 20 15 10"): String {
val parts = inputText.trim().split(" ").filter { it.isNotEmpty() }
if (parts.isEmpty()) {
return "❌ 错误: 请输入至少一次运动时长,例如: 30 20 15 10"
}
val minutesList = parts.mapNotNull { it.toIntOrNull() }.filter { it > 0 }
if (minutesList.isEmpty()) {
return "❌ 错误: 输入中没有有效的分钟数\n示例: 30 20 15 10"
}
val totalMinutes = minutesList.sum()
val count = minutesList.size
val averageMinutes = if (count > 0) totalMinutes / count else 0
val maxMinutes = minutesList.maxOrNull() ?: 0
val minMinutes = minutesList.minOrNull() ?: 0
val weightKg = 65
val met = 6.0
val totalHours = totalMinutes / 60.0
val totalCalories = weightKg * met * totalHours
val totalCaloriesRounded = (totalCalories * 10).toInt() / 10.0
val lightSessions = minutesList.count { it in 1..20 }
val mediumSessions = minutesList.count { it in 21..40 }
val hardSessions = minutesList.count { it > 40 }
val intensityComment = when {
hardSessions >= 1 -> "包含较长时间的高强度运动,请注意充分热身和拉伸,避免运动损伤。"
mediumSessions >= 2 -> "本次运动以中等时长为主,有利于提升心肺耐力,可以继续保持。"
else -> "多为短时运动,可以考虑适当延长单次运动时间,提高训练效果。"
}
val durationComment = when {
totalMinutes >= 150 -> "本周累计运动时长已经接近或超过常见健康建议值,对心血管健康非常有利。"
totalMinutes in 60..149 -> "今日运动时长不错,如果能保持每周多天达到这个水平,会有明显收益。"
else -> "当前总运动时长偏少,可以从每天 10~15 分钟的轻量活动开始逐步增加。"
}
val readableList = minutesList.joinToString(" ") { it.toString() + "min" }
return "🏃 运动记录与热量消耗分析..." // 实际项目中为完整多行说明
}
这是运动记录与热量消耗分析的核心实现函数,展示了完整的运动分析算法。函数使用 @OptIn(ExperimentalJsExport::class) 和 @JsExport 注解,使其可以被编译成 JavaScript 并在 ArkTS 中调用。函数首先进行输入解析,使用 split(" ") 分割输入字符串,使用 filter { it.isNotEmpty() } 过滤空字符串。然后验证输入格式,检查是否包含有效的分钟数。使用 mapNotNull { it.toIntOrNull() } 安全转换数字,避免非法输入导致崩溃。计算基础统计数据:总运动时长、平均时长、最长和最短运动时间。使用 MET 模型计算热量消耗:消耗 (kcal) = 体重(kg) × MET × 时间(h)。按运动强度分类统计:轻量(1-20分钟)、中等(21-40分钟)、高强度(>40分钟)。根据运动结构和总时长生成相应的建议。最后使用字符串模板和 joinToString() 格式化输出完整的分析报告。这个函数展示了如何将复杂的运动分析转换为用户友好的输出。
这里使用了一个非常粗略但直观的能量消耗模型:
- 假设体重为 65kg;
- 假设运动属于 中等强度(约 6 MET);
- 使用公式:
消耗 (kcal) ≈ 体重(kg) × MET × 时间(h); - 只用于教学和演示,不适合作为医学或运动处方依据。
3. JS/ES Module 导出与复用
和其它案例一样,exerciseCaloriesAnalyzer 会随 Kotlin/JS 编译被导出到 hellokjs.mjs 中,并在 hellokjs.d.ts 中生成对应的类型声明。通过项目提供的 build-and-copy.bat 脚本,我们可以自动将这些文件复制到 ArkTS 页面所在的 pages 目录,并重命名为 hellokjs.js 供 ArkTS 导入。
在纯 JavaScript 环境下,使用方式非常简单(示意):
import { exerciseCaloriesAnalyzer } from './hellokjs.mjs';
const input = '30 20 15 10';
const result = exerciseCaloriesAnalyzer(input);
console.log(result);
这段代码展示了如何在 JavaScript 环境中调用编译后的 Kotlin 函数。首先使用 import 语句从编译后的 JavaScript 模块 hellokjs.mjs 中导入 exerciseCaloriesAnalyzer 函数。定义输入字符串 '30 20 15 10',表示四次运动的时长(单位分钟)。调用 exerciseCaloriesAnalyzer(input) 函数,传入输入字符串,获取运动分析结果。使用 console.log() 输出结果。这展示了 KMP 的跨端能力,同一份 Kotlin 代码可以在 JavaScript 环境中无缝调用。编译器自动处理了 Kotlin 的类型系统到 JavaScript 的转换,使得调用方式和普通 JavaScript 函数完全相同。
这种模式说明:Kotlin 写的业务逻辑可以同时为 Web、Node.js、OpenHarmony 等多个端服务,只需要保证 JS 运行时支持 ES Module 即可。
4. ArkTS 页面:在 Index.ets 中调用运动分析
当前工程中,Index.ets 已经切换为本案例:
import { exerciseCaloriesAnalyzer } from './hellokjs';
@Entry
@Component
struct Index {
@State message: string = '请输入运动时长记录,例如: 30 20 15 10';
@State inputText: string = '30 20 15 10';
@State resultText: string = '';
aboutToAppear(): void {
this.analyzeExercise();
}
analyzeExercise(): void {
try {
const input: string = this.inputText;
const result: string = exerciseCaloriesAnalyzer(input);
this.resultText = result;
this.message = '✓ 分析完成';
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.message = `✗ 错误: ${errorMessage}`;
}
}
build() {
Column() {
// 顶部标题栏 + 输入区 + 结果区(完整代码见项目)
}
}
}
这段 ArkTS 代码是鸿蒙应用的用户界面实现,展示了如何在 ArkTS 中导入和调用编译后的 Kotlin 函数。首先使用 import 语句从编译后的 JavaScript 模块中导入 exerciseCaloriesAnalyzer 函数。使用 @State 装饰器定义三个响应式状态变量:message 用于显示状态信息,inputText 存储用户输入的运动时长记录,resultText 存储分析结果。aboutToAppear() 生命周期函数在组件加载时自动调用 analyzeExercise() 进行初始分析。analyzeExercise() 方法调用 Kotlin 编译的 JavaScript 函数 exerciseCaloriesAnalyzer(),将用户输入的文本传入,获取运动分析结果,然后更新 resultText 和 message。使用 try-catch 块捕获异常,如果发生错误则显示错误信息。build() 方法构建整个 UI 布局。这个结构实现了清晰的前后端职责划分:ArkTS 只负责收集输入和展示结果,所有运动分析逻辑都集中在 Kotlin 中。
UI 上的交互逻辑:
- 输入框默认示例:
30 20 15 10; - “开始运动分析”按钮触发
analyzeExercise(),该方法内部调用 Kotlin 导出的exerciseCaloriesAnalyzer; - 滚动区域展示分析结果,包括基础统计、热量估算和结构分析等内容。
5. 生成与复制 hellokjs 文件的流程
在项目根目录执行:
cd /d d:\flutter_Obj\kmp_openharmony
build-and-copy.bat
这段代码展示了如何执行自动化构建脚本。首先使用 cd /d 命令切换到项目根目录 d:\flutter_Obj\kmp_openharmony。然后执行 build-and-copy.bat 脚本,该脚本会自动完成编译和文件复制的全部流程。
脚本会自动:
- 运行
gradlew build,编译 Kotlin/JS,生成包含exerciseCaloriesAnalyzer的新hellokjs.mjs和hellokjs.d.ts; - 检查输出文件是否存在;
- 把它们复制到
kmp_ceshiapp/entry/src/main/ets/pages/目录,并将.mjs重命名为.js; - ArkTS 侧通过
import { exerciseCaloriesAnalyzer } from './hellokjs';使用最新逻辑。
这套流程在“睡眠分析”“饮水分析”“汇率转换”等案例中已经被反复验证,只要新增的 Kotlin 函数标记了 @JsExport,就可以无缝接入。
6. 设计思路与实践价值
设计上为什么只用分钟列表?
- 对于示例工程来说,一串分钟数字足以体现今天的大致运动结构;
- 输入简单,便于在 ArkTS 的文本框中编辑和测试;
- 后续如果想支持“不同运动类型”(跑步/骑行/游泳等),可以扩展为多行输入或 JSON 格式,在 Kotlin 侧做解析。
热量估算的作用是什么?
- 并非为了给出精确结果,而是为了量级感知:让用户大致知道“今天这些运动大概消耗了多少能量”;
- 有助于与饮食记录、体重变化等信息结合,构建更完整的生活数据面板;
- 也可以作为教学示例,向读者介绍 MET 的概念及其在编程中的简单应用。
7. 小结
通过“运动记录与热量消耗分析工具”,你可以看到:
- 如何在 Kotlin 中实现一个纯逻辑的运动分析函数
exerciseCaloriesAnalyzer; - 如何利用 Kotlin/JS IR 将这段逻辑导出为 JavaScript 模块
hellokjs.js; - 如何在 OpenHarmony ArkTS 页面中用极少的胶水代码完成导入与调用;
- 如何通过统一的 README 文档将 Kotlin/JS/ArkTS 三者串联成一条清晰的知识线索。
结合前面的“睡眠”“饮水”“汇率”等案例,你已经拥有一套相对完整的 KMP + OpenHarmony 跨端健康/工具 Demo 集。未来要继续扩展新的场景,只需在 Kotlin 中新增函数、跑一遍脚本、修改少量 ArkTS UI,即可快速完成一个新的小应用。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)