在这里插入图片描述

1. 应用概述

血压记录(BloodPressure)是一款基于HarmonyOS ArkTS框架开发的健康数据记录工具,其核心功能是帮助用户记录每日血压数值、追踪血压变化趋势、评估血压健康状态。这款应用将传统的血压记录方式数字化,提供直观的数值输入、历史记录展示和智能状态评估功能,为用户的血压健康管理提供数据支持。

在技术实现层面,血压记录应用充分展示了HarmonyOS声明式UI开发范式的核心能力。通过@State装饰器实现响应式状态管理,TextInput组件实现血压数值输入,List组件实现历史记录列表渲染,状态判断算法实现血压分类评估,以及清晰的列表卡片UI设计,构成了一个功能聚焦的血压健康助手应用。应用的代码结构简洁清晰,使用HarmonyOS原生API完成所有功能实现,没有引入任何复杂的第三方依赖。

本技术博客将从应用架构设计、核心代码实现、血压评估算法、数据模型设计、状态管理机制、List组件使用以及健康类应用设计要点等多个维度,对这款血压记录应用进行全面的技术剖析。通过本文的深入讲解,读者不仅能够理解如何实现一个功能完善的血压记录应用,更能够掌握HarmonyOS ArkTS开发中的核心知识点,特别是TextInput输入处理、List列表渲染、状态判断逻辑、健康数据评估以及健康类应用的设计要点等关键技术点。

2. 技术架构分析

2.1 整体架构设计

血压记录应用采用了单页面架构(Single Page Application),整个应用仅包含一个主页面,通过组件化设计将UI展示与业务逻辑进行有效分离。从代码组织角度来看,应用主要分为以下几个核心部分:页面入口组件(BloodPressure)、通用标题栏组件(CommonTitleBar)、数值输入区、添加按钮区以及历史记录列表区。

在ArkUI框架中,每一个页面都是一个独立的@Component装饰器组件。BloodPressure组件作为整个应用的根组件,负责管理所有的状态变量和业务逻辑,包括收缩压输入值、舒张压输入值、血压记录列表、状态评估结果等。UI渲染通过build()方法中的声明式代码完成,所有UI更新都由状态变量变化自动触发。

┌─────────────────────────────────────────────────────────┐
│                   BloodPressure页面                     │
│  ┌─────────────────────────────────────────────────┐    │
│  │              CommonTitleBar组件                  │    │
│  │              (导航栏+标题显示)                    │    │
│  └─────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────┐    │
│  │              数值输入区                          │    │
│  │              (收缩压 + 舒张压输入框)              │    │
│  └─────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────┐    │
│  │              添加按钮区                          │    │
│  │              (添加记录按钮)                       │    │
│  └─────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────┐    │
│  │              历史记录列表区                      │    │
│  │              (日期+数值+状态)                    │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

2.2 模块依赖关系

从依赖关系的角度分析,血压记录应用主要依赖以下几个核心模块:

首先是CommonTitleBar组件,该组件提供了统一的页面标题栏和返回按钮功能。作为项目中的通用组件,CommonTitleBar被多个页面复用,确保了应用内导航体验的一致性。

TextInput组件是ArkUI框架提供的文本输入控件,用于接收用户的血压数值输入。应用使用两个TextInput分别输入收缩压和舒张压数值。

List组件是ArkUI框架提供的列表渲染控件,用于展示历史血压记录列表。通过ForEach循环渲染每个记录项。

Button组件是ArkUI框架提供的按钮控件,用于触发添加记录操作。

2.3 数据模型设计

血压记录应用的数据模型包含以下核心状态变量:

@State app_records: Record<string, string>[] = [];  // 血压记录列表
@State app_systolic: string = '';                    // 收缩压输入值
@State app_diastolic: string = '';                   // 舒张压输入值
状态变量 类型 初始值 说明
app_records Record[] [] 血压记录数组,每条记录包含日期、收缩压、舒张压、状态
app_systolic string ‘’ 用户输入的收缩压数值
app_diastolic string ‘’ 用户输入的舒张压数值

记录项的数据结构:

interface BloodPressureRecord {
  date: string;      // 记录日期
  systolic: string;   // 收缩压数值(mmHg)
  diastolic: string;  // 舒张压数值(mmHg)
  status: string;    // 血压状态评估结果
}

血压状态的取值范围:

状态 收缩压条件 舒张压条件 医学含义
正常 < 120 mmHg < 80 mmHg 血压在健康范围内
偏高 120-139 mmHg 80-89 mmHg 处于高血压前期
高血压 >= 140 mmHg >= 90 mmHg 确诊高血压

3. 核心代码详解

3.1 状态管理机制

血压记录应用的状态管理遵循ArkTS框架的核心设计理念,使用@State装饰器声明响应式状态变量。

@State app_records: Record<string, string>[] = [];
@State app_systolic: string = '';
@State app_diastolic: string = '';

ArkTS作为静态类型语言,要求所有变量必须显式声明类型。这里的类型声明(Record[]、string)都是不可或缺的。

状态变量的职责划分:

app_records:存储血压记录列表,是应用的核心数据。用户添加的每条记录都会push到这个数组中,List组件会自动渲染这个数组的所有元素。

app_systolic:存储用户输入的收缩压数值。这是一个临时状态,每次输入变化时都会更新,当用户提交记录后会清空。

app_diastolic:存储用户输入的舒张压数值。与收缩压类似,也是临时状态。

3.2 数值输入处理

血压记录使用TextInput组件接收用户输入:

Row({ space: 12 }) {
  Column() {
    Text('收缩压')
      .fontSize(12)
      .fontColor($r('app.color.app_color_text_tertiary'))
    TextInput({ placeholder: 'mmHg' })
      .width('100%')
      .onChange((app_value: string) => {
        this.app_systolic = app_value;
      })
  }
  .layoutWeight(1)

  Column() {
    Text('舒张压')
      .fontSize(12)
      .fontColor($r('app.color.app_color_text_tertiary'))
    TextInput({ placeholder: 'mmHg' })
      .width('100%')
      .onChange((app_value: string) => {
        this.app_diastolic = app_value;
      })
  }
  .layoutWeight(1)
}

TextInput组件的关键配置:

placeholder属性:设置输入框的占位提示文字"mmHg",告诉用户应该输入什么单位

onChange事件:每次输入变化时触发回调,更新对应的状态变量

layoutWeight属性:设置为1使两个输入框等宽分布

width(‘100%’):输入框宽度占满容器

3.3 记录添加逻辑实现

血压记录的添加逻辑是应用的核心业务功能:

Button('添加记录')
  .width('100%')
  .onClick(() => {
    let app_record: Record<string, string> = {
      'date': new Date().toLocaleDateString(),
      'systolic': this.app_systolic,
      'diastolic': this.app_diastolic,
      'status': this.app_getStatus()
    };
    this.app_records.push(app_record);
  })

添加记录的业务流程:

1. 创建记录对象:构建一个包含日期、数值和状态的记录对象

2. 获取当前日期:使用new Date().toLocaleDateString()获取当前日期的本地化字符串表示

3. 血压状态评估:调用app_getStatus()方法根据输入数值计算血压状态

4. 添加到列表:使用数组的push方法将记录添加到列表末尾

5. 自动清空输入:输入框的值状态不会自动清空(当前实现),需要在后续优化中改进

3.4 血压状态评估算法

血压状态评估是应用的核心算法,根据医学标准进行判断:

private app_getStatus(): string {
  let app_sys: number = parseInt(this.app_systolic || '0');
  let app_dia: number = parseInt(this.app_diastolic || '0');
  if (app_sys < 120 && app_dia < 80) {
    return '正常';
  } else if (app_sys < 140 && app_dia < 90) {
    return '偏高';
  } else {
    return '高血压';
  }
}

血压评估算法解析:

参数获取:从状态变量中获取收缩压和舒张压数值,使用parseInt转换为数字类型

空值处理:使用|| '0'处理空字符串情况,确保parseInt不会返回NaN

判断逻辑:按照中国高血压防治指南的标准进行三级分类

血压分级标准(依据《中国高血压防治指南2018年修订版》):

分类 收缩压(mmHg) 舒张压(mmHg)
正常血压 < 120 且 < 80
正常高值 120-139 或 80-89
高血压 >= 140 或 >= 90

3.5 状态颜色映射

为了直观展示血压状态,应用使用不同颜色标识不同状态:

private app_getStatusColor(app_status: string): Resource {
  if (app_status === '正常') {
    return $r('app.color.app_color_success');
  } else if (app_status === '偏高') {
    return $r('app.color.app_color_warning');
  } else {
    return $r('app.color.app_color_danger');
  }
}

状态颜色映射规则:

状态 颜色 含义
正常 success(绿色) 血压在健康范围内
偏高 warning(黄色) 处于高血压前期,需要关注
高血压 danger(红色) 血压偏高,需要就医或调整生活习惯

4. UI布局设计

4.1 整体布局结构

血压记录的UI布局采用垂直堆叠的Column容器组织各个功能区块:

build() {
  Column() {
    CommonTitleBar({
      app_title: '血压记录',
      app_showBack: true
    })

    Column({ space: 16 }) {
      // 输入区域
      Row({ space: 12 }) {
        Column() {...}  // 收缩压输入
        Column() {...}  // 舒张压输入
      }

      // 添加按钮
      Button('添加记录')
        .width('100%')
        .onClick(...)

      // 历史记录列表
      List() {
        ForEach(this.app_records, (app_record: Record<string, string>) => {
          ListItem() {...}
        })
      }
      .width('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .padding(16)
  }
  .width('100%')
  .height('100%')
  .backgroundColor($r('app.color.app_color_background'))
}

布局设计采用"输入 -> 添加 -> 列表"的信息流顺序,符合用户的操作习惯。

4.2 输入区域设计

输入区域包含两个并列的血压输入框:

Row({ space: 12 }) {
  Column() {
    Text('收缩压')
      .fontSize(12)
      .fontColor($r('app.color.app_color_text_tertiary'))
    TextInput({ placeholder: 'mmHg' })
      .width('100%')
      .onChange((app_value: string) => {
        this.app_systolic = app_value;
      })
  }
  .layoutWeight(1)

  Column() {
    Text('舒张压')
      .fontSize(12)
      .fontColor($r('app.color.app_color_text_tertiary'))
    TextInput({ placeholder: 'mmHg' })
      .width('100%')
      .onChange((app_value: string) => {
        this.app_diastolic = app_value;
      })
  }
  .layoutWeight(1)
}

设计要点:

Row布局:两个输入框水平并排,使用layoutWeight(1)使它们等宽分布

标签文字:使用小字号(12vp)和灰色文字标注输入项含义

占位提示:placeholder设置为"mmHg",明确数值的单位

间距控制:Row的space: 12控制两个输入框之间的间距

4.3 历史记录列表设计

历史记录列表使用List组件渲染:

List() {
  ForEach(this.app_records, (app_record: Record<string, string>) => {
    ListItem() {
      Row() {
        Column({ space: 4 }) {
          Text(app_record['date'])
            .fontSize(12)
            .fontColor($r('app.color.app_color_text_tertiary'))
          Text(`${app_record['systolic']}/${app_record['diastolic']} mmHg`)
            .fontSize(18)
            .fontWeight(FontWeight.Medium)
            .fontColor($r('app.color.app_color_text_primary'))
        }

        Blank()

        Text(app_record['status'])
          .fontSize(14)
          .fontColor(this.app_getStatusColor(app_record['status']))
      }
      .width('100%')
      .padding(12)
      .backgroundColor($r('app.color.app_color_white'))
      .borderRadius(8)
    }
  })
}
.width('100%')
.layoutWeight(1)

List组件的关键点:

ForEach循环:遍历app_records数组,为每个元素渲染一个ListItem

记录卡片样式:白色背景、8vp圆角、12vp内边距

日期和数值:日期在上方(灰色小字),数值在下方(深色大字)

状态标签:使用不同颜色展示血压状态(绿色/黄色/红色)

Blank组件:将状态标签推到右侧,实现右对齐

5. List组件深入理解

5.1 List组件概述

List组件是ArkUI框架提供的列表渲染组件,用于展示可滚动的数据列表。它是健康类应用展示历史记录的核心组件。

List组件的基本结构:

List() {
  ForEach(items, (item: Type) => {
    ListItem() {
      // 单项内容
    }
  })
}

5.2 ForEach循环渲染

ForEach是ArkUI框架提供的循环渲染指令:

ForEach(
  arr: Array<T>,           // 要遍历的数组
  itemGenerator: (item: T, index: number) => void,  // 生成函数
  keyGenerator?: (item: T, index: number) => string  // 可选的键生成函数
)

ForEach的工作原理:

数据驱动:ForEach会根据数组内容自动渲染UI,数组变化时自动更新列表

键值追踪:通过keyGenerator生成唯一键,追踪每个列表项的身份

性能优化:框架会根据键值判断哪些列表项需要重新渲染

5.3 列表项样式设计

列表项是列表中的单个元素,通常呈现为一个卡片:

ListItem() {
  Row() {
    // 左侧:日期和数值
    Column({ space: 4 }) {...}
    
    // 右侧:状态标签
    Blank()
    Text(app_record['status'])
  }
  .width('100%')
  .padding(12)
  .backgroundColor($r('app.color.app_color_white'))
  .borderRadius(8)
}

列表项样式要点:

背景色:使用白色背景与页面背景区分

圆角:8vp的圆角提供柔和的视觉感受

内边距:12vp的内边距确保内容不贴近边缘

宽度:width(‘100%’)使列表项占满列表宽度

6. 血压健康知识

6.1 血压基本概念

血压是血液在血管内流动时对血管壁产生的压力。心室收缩时,血液从心室泵入动脉,此时动脉血压的最高值称为收缩压(俗称"高压")。心室舒张时,动脉血压降至最低,称为舒张压(俗称"低压")。

血压表示方法:

// 标准表示:收缩压/舒张压 mmHg
"120/80 mmHg"
// 收缩压120,舒张压80

6.2 正常血压范围

根据《中国高血压防治指南2018年修订版》:

分类 收缩压(mmHg) 舒张压(mmHg)
正常血压 < 120 且 < 80
正常高值 120-139 或 80-89
高血压 >= 140 或 >= 90

6.3 血压测量注意事项

正确的血压测量对于获得准确数据至关重要:

测量前准备:测量前30分钟避免剧烈运动、进食、饮酒或吸烟

测量姿势:坐着测量时,背部有支撑,手臂放在心脏水平高度

测量环境:保持安静,避免说话

测量频率:建议早晚各测量一次,取平均值记录

7. 数据持久化

7.1 AppStorage存储机制

血压记录应用应该使用AppStorage实现数据的持久化存储。在HarmonyOS中,AppStorage是应用级的状态存储服务,提供了键值对形式的轻量级数据存储能力。

// 保存血压记录
app_saveRecords(): void {
  app_setString('bp_records', JSON.stringify(this.app_records));
}

// 加载血压记录
app_loadRecords(): void {
  const app_recordsStr: string = app_getString('bp_records', '[]');
  try {
    this.app_records = JSON.parse(app_recordsStr);
  } catch (error) {
    this.app_records = [];
  }
}

数据持久化的执行时机:

生命周期 执行操作
aboutToAppear app_loadRecords()
aboutToDisappear app_saveRecords()
添加记录后 app_saveRecords()

7.2 JSON序列化存储

血压记录数组可以直接序列化为JSON字符串进行存储:

// 保存
const app_jsonStr: string = JSON.stringify(this.app_records);
app_setString('bp_records', app_jsonStr);

// 加载
const app_jsonStr: string = app_getString('bp_records', '[]');
this.app_records = JSON.parse(app_jsonStr);

JSON格式存储的优点是可以完整保存记录数组的结构,包括日期、数值和状态所有字段。

8. 扩展与展望

8.1 当前功能总结

血压记录应用实现了以下核心功能:

功能模块 实现描述
血压输入 两个输入框分别输入收缩压和舒张压
状态评估 根据医学标准判断血压状态(正常/偏高/高血压)
记录添加 将血压数据和时间戳添加到记录列表
记录展示 用List组件展示历史血压记录
状态颜色 用颜色区分不同血压状态

8.2 功能扩展方向

基于当前的血压记录应用架构,可以进行以下功能扩展:

图表展示:添加血压趋势图表,直观展示血压变化趋势。

// 使用chart组件绘制趋势图
Chart()
  .type(ChartType.Line)
  .dataSet(this.app_bpHistory)

数据导出:支持将血压记录导出为CSV或PDF格式。

// 导出为CSV
let app_csv: string = '日期,收缩压,舒张压,状态\n';
for (let i = 0; i < this.app_records.length; i++) {
  const app_r: Record<string, string> = this.app_records[i];
  app_csv += `${app_r['date']},${app_r['systolic']},${app_r['diastolic']},${app_r['status']}\n`;
}

提醒功能:在固定时间提醒用户测量血压。

// 使用通知提醒
notification.publish({
  id: 1002,
  content: {
    title: '血压提醒',
    text: '该测量血压了'
  }
});

血压分类细化:将高血压进一步分为1级、2级、3级。

private app_getDetailedStatus(): string {
  let app_sys: number = parseInt(this.app_systolic || '0');
  let app_dia: number = parseInt(this.app_diastolic || '0');
  
  if (app_sys >= 180 || app_dia >= 110) {
    return '3级高血压(重度)';
  } else if (app_sys >= 160 || app_dia >= 100) {
    return '2级高血压(中度)';
  } else if (app_sys >= 140 || app_dia >= 90) {
    return '1级高血压(轻度)';
  }
  // ...
}

平均值计算:计算一段时间内的平均血压值。

private app_getAverage(): { sys: number; dia: number } {
  if (this.app_records.length === 0) {
    return { sys: 0, dia: 0 };
  }
  let app_totalSys: number = 0;
  let app_totalDia: number = 0;
  for (let i = 0; i < this.app_records.length; i++) {
    app_totalSys += parseInt(this.app_records[i]['systolic'] || '0');
    app_totalDia += parseInt(this.app_records[i]['diastolic'] || '0');
  }
  return {
    sys: Math.round(app_totalSys / this.app_records.length),
    dia: Math.round(app_totalDia / this.app_records.length)
  };
}

数据同步:支持将数据同步到云端,实现多设备访问。

9. 健康类应用设计要点

9.1 数据准确性

健康类应用的数据准确性直接影响用户的健康决策:

输入验证:对用户输入的数值进行合理性校验,如血压范围应在30-250 mmHg之间

private app_validateInput(app_sys: string, app_dia: string): boolean {
  let app_sysNum: number = parseInt(app_sys);
  let app_diaNum: number = parseInt(app_dia);
  
  if (isNaN(app_sysNum) || isNaN(app_diaNum)) {
    return false;  // 非数字
  }
  if (app_sysNum < 30 || app_sysNum > 250) {
    return false;  // 超出合理范围
  }
  if (app_diaNum < 30 || app_diaNum > 150) {
    return false;  // 超出合理范围
  }
  if (app_sysNum <= app_diaNum) {
    return false;  // 收缩压应该大于舒张压
  }
  return true;
}

明确数据来源:记录应该基于用户手动输入或校准后的设备读数

合理默认值:不提供可能误导用户的默认值

9.2 医学参考

健康类应用的健康评估应该基于权威医学指南:

引用国家标准:本应用参照《中国高血压防治指南》进行血压分级

清晰告知用户:评估结果仅供参考,不能替代专业医疗诊断

建议就医场景:当血压处于高血压范围时,明确建议用户咨询医生

9.3 隐私保护

健康数据属于敏感个人信息:

本地存储优先:数据存储在设备本地,不上传到服务器

用户控制权:用户可以查看、导出和删除自己的数据

最小化收集:只收集功能必需的数据

10. 技术要点总结

10.1 ArkTS核心特性使用

通过血压记录应用,我们可以总结以下ArkTS核心特性的使用方法:

@State装饰器:用于声明组件级别的响应式状态

@State app_records: Record<string, string>[] = [];
@State app_systolic: string = '';
@State app_diastolic: string = '';

TextInput组件:用于接收用户文本输入

TextInput({ placeholder: 'mmHg' })
  .width('100%')
  .onChange((app_value: string) => {
    this.app_systolic = app_value;
  })

List + ForEach:用于渲染列表数据

List() {
  ForEach(this.app_records, (app_record: Record<string, string>) => {
    ListItem() {...}
  })
}

10.2 条件判断技巧

血压评估使用多级条件判断:

if (app_sys < 120 && app_dia < 80) {
  return '正常';
} else if (app_sys < 140 && app_dia < 90) {
  return '偏高';
} else {
  return '高血压';
}

判断顺序很重要:应该从最严格的条件开始判断,逐步放宽。

10.3 状态颜色映射

使用函数封装颜色映射逻辑,便于维护和扩展:

private app_getStatusColor(app_status: string): Resource {
  if (app_status === '正常') {
    return $r('app.color.app_color_success');
  } else if (app_status === '偏高') {
    return $r('app.color.app_color_warning');
  } else {
    return $r('app.color.app_color_danger');
  }
}

10.4 健康类应用架构建议

健康类应用的技术架构建议:

数据模型设计:使用接口定义清晰的数据结构

interface BloodPressureRecord {
  date: string;
  systolic: string;
  diastolic: string;
  status: string;
}

输入验证:在添加记录前验证输入数据的合理性

private app_validateInput(sys: string, dia: string): boolean {
  // 验证逻辑
}

持久化存储:使用AppStorage存储历史数据

app_setString('bp_records', JSON.stringify(this.app_records));

希望本文对血压记录应用的技术剖析能够帮助开发者深入理解HarmonyOS ArkTS的开发范式和核心API使用技巧,特别是TextInput输入处理、List列表渲染、条件判断逻辑、健康数据评估以及健康类应用的设计要点等关键技术点。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐