Kotlin BMI体质指数计算器 - KMP鸿蒙跨端实现

目录
- 概述
- BMI 算法原理
- Kotlin 实现代码(KMP)
- 编译后的 JavaScript 代码说明
- ArkTS 页面集成与调用
- 交互示例
- 编译与文件复制流程
- 总结
概述
本案例展示如何使用 Kotlin Multiplatform (KMP) 编写一个 BMI 体质指数计算器,并通过 Kotlin/JS 编译为 JavaScript,最终在 OpenHarmony ArkTS 页面 中调用,实现鸿蒙端的跨语言复用。
特点:
- 输入:身高(cm)+ 体重(kg)
- 输出:BMI 数值、体型分类、理想体重区间、增减重建议、健康提示
- 技术栈:Kotlin(Multiplatform)→ JavaScript(ESModule)→ ArkTS(UI 页面)
BMI 算法原理
BMI(Body Mass Index,体质指数)的计算公式为:
BMI = 体重(kg) / 身高(m)^2
常见的分类(此处采用简化的中国成人标准):
- BMI < 18.5 → 偏瘦
- 18.5 ≤ BMI < 24.0 → 正常
- 24.0 ≤ BMI < 28.0 → 超重
- BMI ≥ 28.0 → 肥胖
理想体重区间可以根据 BMI 正常区间(18.5 ~ 24.0)反推:
理想体重下限 = 18.5 × 身高(m)^2
理想体重上限 = 24.0 × 身高(m)^2
Kotlin 实现代码(KMP)
下面是定义在 src/jsMain/kotlin/App.kt 中的 bmiCalculator 方法,通过 @JsExport 导出供 JS/ArkTS 调用:
@OptIn(ExperimentalJsExport::class)
@JsExport
fun bmiCalculator(inputText: String = "170 65"): String {
val parts = inputText.trim().split(" ").filter { it.isNotEmpty() }
if (parts.size < 2) {
return "❌ 错误: 请按 '身高 体重' 的格式输入,例如: 170 65"
}
val heightCm = parts[0].toDoubleOrNull()
val weightKg = parts[1].toDoubleOrNull()
if (heightCm == null || weightKg == null || heightCm <= 0 || weightKg <= 0) {
return "❌ 错误: 身高或体重无效\n请输入正数,例如: 170 65"
}
// 1. 计算 BMI
val heightM = heightCm / 100.0
val bmi = weightKg / (heightM * heightM)
val bmiRounded = (bmi * 10).toInt() / 10.0
// 2. 体型分类
val category = when {
bmi < 18.5 -> "偏瘦"
bmi < 24.0 -> "正常"
bmi < 28.0 -> "超重"
else -> "肥胖"
}
// 3. 理想体重区间
val minWeight = 18.5 * heightM * heightM
val maxWeight = 24.0 * heightM * heightM
// 4. 当前与理想区间的差值
val deltaToMin = weightKg - minWeight
val deltaToMax = weightKg - maxWeight
// 5. 增减重建议
val adjustSuggestion = when {
bmi < 18.5 -> {
val gain = (minWeight - weightKg)
val gainRounded = (gain * 10).toInt() / 10.0
"建议增重约 ${gainRounded}kg 以达到正常范围下限。"
}
bmi > 24.0 -> {
val lose = (weightKg - maxWeight)
val loseRounded = (lose * 10).toInt() / 10.0
"建议减重约 ${loseRounded}kg 以回到正常范围上限。"
}
else -> "目前体重在正常范围内,继续保持良好生活习惯。"
}
// 6. 健康提示
val healthTip = when {
bmi < 18.5 -> "注意营养均衡,多摄入优质蛋白和复合碳水,避免过度节食。"
bmi < 24.0 -> "继续保持规律作息和适量运动,是当前最好的状态。"
bmi < 28.0 -> "建议增加有氧运动,适当控制精制碳水和高脂肪食物摄入。"
else -> "建议在专业人士指导下进行饮食控制和运动计划,循序渐进减重。"
}
return "⚖️ BMI 体质指数计算器\n" +
"━━━━━━━━━━━━━━━━━━━━━\n" +
"输入: 身高 ${heightCm}cm, 体重 ${weightKg}kg\n\n" +
"1️⃣ 计算结果:\n" +
" BMI: ${bmiRounded}\n" +
" 体型: ${category}\n\n" +
"2️⃣ 理想体重区间:\n" +
" 范围: ${(minWeight * 10).toInt() / 10.0}kg ~ ${(maxWeight * 10).toInt() / 10.0}kg\n" +
" 当前相对下限: ${(deltaToMin * 10).toInt() / 10.0}kg\n" +
" 当前相对上限: ${(deltaToMax * 10).toInt() / 10.0}kg\n\n" +
"3️⃣ 调整建议:\n" +
" ${adjustSuggestion}\n\n" +
"4️⃣ 健康提示:\n" +
" ${healthTip}\n\n" +
"━━━━━━━━━━━━━━━━━━━━━\n" +
"✅ 分析完成!"
}
代码说明:
这个 bmiCalculator 函数是整个 BMI 计算器的核心逻辑,使用 @JsExport 注解将其导出为 JavaScript 可调用的函数。函数接收一个字符串参数 inputText,格式为"身高 体重"(例如"170 65"),默认值为"170 65"。
首先,函数对输入进行解析和验证。它将输入字符串按空格分割,并过滤掉空字符串。如果分割后的部分少于 2 个,说明输入格式不正确,返回错误提示。然后尝试将身高和体重转换为浮点数,使用 toDoubleOrNull() 方法安全地进行转换。如果转换失败或数值为负数或零,同样返回错误提示。
接下来进行 BMI 的计算。首先将身高从厘米转换为米(除以 100),然后使用公式 BMI = 体重 / 身高² 计算 BMI 值。为了提高可读性,将 BMI 值四舍五入到小数点后一位。
基于计算出的 BMI 值,使用 when 表达式进行体型分类。根据不同的 BMI 范围(偏瘦、正常、超重、肥胖)返回对应的分类结果。
然后计算理想体重区间。根据 BMI 正常范围(18.5 ~ 24.0)反推出对应身高下的最小和最大理想体重。同时计算当前体重与理想范围上下限的差值,用于后续的调整建议。
增减重建议部分根据当前 BMI 值判断用户的体重状态。如果 BMI 小于 18.5(偏瘦),计算需要增加的体重;如果 BMI 大于 24.0(超重或肥胖),计算需要减少的体重;如果在正常范围内,则建议保持现状。
最后,根据 BMI 值提供个性化的健康提示,包括营养建议、运动建议等。函数返回一个格式化的多行字符串,包含所有计算结果、分类、建议和提示,使用 emoji 和分隔符使输出更加直观易读。
编译后的 JavaScript 代码说明
Kotlin/JS 编译后生成的文件位置:
build/js/packages/hellokjs/kotlin/hellokjs.mjs
build/js/packages/hellokjs/kotlin/hellokjs.d.ts
在 hellokjs.mjs 中,对应会生成一个 bmiCalculator 导出函数,伪代码结构类似:
export function bmiCalculator(inputText = "170 65") {
// 解析输入
// 计算 BMI
// 拼接多行字符串
return resultString;
}
代码说明:
这是 Kotlin 编译后生成的 JavaScript 代码的伪代码表示。实际编译生成的代码会包含 Kotlin 运行时库和完整的函数实现。export 关键字使得这个函数可以被其他 JavaScript 模块导入使用。函数接收一个可选的字符串参数 inputText,默认值为"170 65"。函数内部的注释表示了三个主要步骤:首先解析用户输入的身高和体重数据,然后根据公式计算 BMI 值并进行分类,最后将所有结果拼接成一个格式化的多行字符串返回给调用者。这种导出方式使得 ArkTS 页面可以像调用普通 JavaScript 函数一样调用 Kotlin 编写的业务逻辑。
同时 .d.ts 文件中会有类型声明:
export declare function bmiCalculator(inputText?: string): string;
代码说明:
这是 TypeScript 类型声明文件,为编译生成的 JavaScript 函数提供类型信息。export declare 表示这是一个导出的函数声明。函数名为 bmiCalculator,接收一个可选的字符串参数 inputText(问号表示可选),返回值类型为 string。这个类型声明文件的作用是在 ArkTS/TypeScript 开发环境中提供代码补全、类型检查和文档提示,帮助开发者正确使用这个函数。当在 ArkTS 中导入 bmiCalculator 时,IDE 会根据这个声明文件提供自动补全和类型验证,确保调用的正确性。
ArkTS 页面集成与调用
在 OpenHarmony 工程中,我们将 hellokjs.mjs 复制并重命名为 hellokjs.js,放到 ArkTS 页面的同级目录,然后在 Index.ets 中导入并调用:
import { bmiCalculator } from './hellokjs';
@Entry
@Component
struct Index {
@State message: string = '请输入身高和体重';
@State inputHeight: string = '170';
@State inputWeight: string = '65';
@State resultText: string = '';
aboutToAppear(): void {
this.calculateBmi();
}
calculateBmi(): void {
try {
const input: string = `${this.inputHeight} ${this.inputWeight}`;
const result: string = bmiCalculator(input);
this.resultText = result;
this.message = '✓ 计算完成';
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.message = `✗ 错误: ${errorMessage}`;
}
}
build() {
Column() {
// 顶部标题栏、输入区域、结果展示等(略,见工程中的 Index.ets 完整代码)
}
}
}
代码说明:
这是 OpenHarmony ArkTS 页面的核心代码,展示了如何集成和调用 Kotlin 编译生成的 JavaScript 函数。首先通过 import 语句从 ./hellokjs 模块导入 bmiCalculator 函数,这个模块就是之前编译生成的 JavaScript 文件。
@Entry 和 @Component 装饰器表示这是一个可入口的组件,是页面的主体。struct Index 定义了页面的结构体。
页面使用 @State 装饰器定义了四个响应式状态变量:message 用于显示状态提示信息,inputHeight 和 inputWeight 分别存储用户输入的身高和体重(初始值为"170"和"65"),resultText 用于存储 BMI 计算的结果。
aboutToAppear() 是生命周期钩子,在组件即将显示时被调用,这里调用 calculateBmi() 方法进行初始计算。
calculateBmi() 方法是关键的业务逻辑调用点。它首先将输入的身高和体重拼接成"身高 体重"的格式字符串,然后调用 Kotlin 编译生成的 bmiCalculator 函数,就像调用普通的 JavaScript 函数一样。函数返回的结果字符串被存储在 resultText 中,并更新 message 为成功提示。整个调用被包裹在 try-catch 块中,以便捕获任何可能的错误并显示错误信息。
build() 方法定义了页面的 UI 布局,使用 Column 组件作为主容器(具体的 UI 代码在这里省略)。这种设计模式清晰地分离了关注点:Kotlin 负责复杂的业务算法,ArkTS 只负责 UI 展示和用户交互。
交互示例
示例 1:标准体重
输入:
身高: 170cm
体重: 65kg
输出片段示例:
1️⃣ 计算结果:
BMI: 22.5
体型: 正常
2️⃣ 理想体重区间:
范围: 53.5kg ~ 69.4kg
当前相对下限: 11.5kg
当前相对上限: -4.4kg
3️⃣ 调整建议:
目前体重在正常范围内,继续保持良好生活习惯。
示例 2:偏瘦
输入: 170 48
会给出:
- BMI 数值较低
- 体型为“偏瘦”
- 建议增重若干 kg
- 给出营养与作息方面的健康提示
示例 3:超重 / 肥胖
输入: 170 85
会给出:
- BMI 偏高
- 对应“超重”或“肥胖”分类
- 建议减重的 kg 数
- 生活方式调整建议(有氧运动、饮食控制等)
编译与文件复制流程
工程中已经通过脚本将编译与文件复制自动化:
# 在项目根目录执行
build-and-copy.bat
代码说明:
这是一个 Windows 批处理脚本,用于自动化 Kotlin/JS 编译和文件复制的整个流程。脚本的主要目的是简化开发者的工作流程,避免手动执行多个步骤。脚本主要做三件事:首先执行 gradlew build 命令编译 Kotlin 代码为 JavaScript,这个过程会生成 ES Module 格式的 JavaScript 文件和对应的 TypeScript 类型声明文件。其次检查编译是否成功,验证 hellokjs.mjs 和 hellokjs.d.ts 文件是否已经生成在 build 目录中。最后将生成的文件复制到 ArkTS 页面所在的目录,并将 .mjs 文件重命名为 .js,这样做是为了兼容 OpenHarmony 的模块加载机制。
目标位置:
d:\flutter_Obj\kmp_openharmony\kmp_ceshiapp\entry\src\main\ets\pages\hellokjs.js
d:\flutter_Obj\kmp_openharmony\kmp_ceshiapp\entry\src\main\ets\pages\hellokjs.d.ts
代码说明:
这两行文本指定了编译后的 JavaScript 文件和 TypeScript 类型声明文件的最终目标位置。第一个路径指向重命名后的 JavaScript 文件 hellokjs.js,这是 ArkTS 页面实际导入和使用的文件。第二个路径指向 TypeScript 类型声明文件 hellokjs.d.ts,它为 IDE 和编译器提供类型信息,使得在 ArkTS 中调用 Kotlin 编写的函数时能够获得完整的类型检查和代码补全支持。这两个文件都被放在 OpenHarmony 工程的 pages 目录中,与 ArkTS 页面文件放在一起,方便导入和使用。
总结
通过 BMI 体质指数计算器案例,我们完成了:
- 使用 Kotlin 编写可复用的业务算法(BMI 计算 + 文本分析)
- 通过 Kotlin/JS 将其编译为 JavaScript 模块
- 在 OpenHarmony ArkTS 页面中直接导入并调用该模块
- 实现“算法在 Kotlin,界面在 ArkTS”的清晰分层
你可以用同样的方式继续扩展更多工具或小应用(如贷款计算器、营养配比工具等),只需:
- 在
App.kt中添加新的@JsExport方法 - 通过脚本重新编译并复制 JS 文件
- 在 ArkTS 页面中导入并调用新的函数
这就是 KMP 在鸿蒙端实战中的一个完整链路示例。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)