React Native鸿蒙跨平台 HarmonyOS ArkTS API 24 完成不可变的状态更新机制(如`setHealthData保证了健康数据的一致性
在健康管理数字化的大趋势下,健康数据聚合类应用需要兼顾多维度数据采集、趋势分析与跨端访问能力,而鸿蒙系统作为新一代分布式操作系统,成为健康应用跨端部署的重要目标平台。本文将深度拆解基于React Native开发的健康数据聚合应用代码,从多维度健康数据模型设计、实时趋势计算逻辑、UI交互适配到鸿蒙系统跨端兼容的核心技术要点,全方位剖析健康数据类跨端应用的开发范式与最佳实践。
底层逻辑
这款健康数据聚合应用聚焦于步数、心率、睡眠等核心健康指标的全生命周期管理,涵盖用户健康档案、多维度数据录入、周期趋势分析、医生数据共享等核心功能。从架构层面来看,应用完全基于React Native的组件化思想构建,以TypeScript作为开发语言实现强类型约束,这种设计既保证了健康数据的准确性和可维护性,也为鸿蒙系统的跨端兼容奠定了核心基础。
从跨端适配的底层逻辑分析,代码中未引入任何平台专属API(如iOS的HealthKit、Android的Google Fit或鸿蒙的Health Ability),所有核心功能均基于React Native的通用核心组件(SafeAreaView、View、Text、TextInput、Modal等)和基础API(Dimensions、Alert、TouchableOpacity)构建。在鸿蒙系统中,这些通用组件会被React Native for HarmonyOS框架转换为ArkUI原生组件——例如TouchableOpacity映射为鸿蒙的Button组件、Modal映射为鸿蒙的Dialog组件,从而保证UI渲染和交互逻辑在鸿蒙设备上的一致性。这种“通用抽象层+平台适配层”的架构,避免了因平台差异导致的代码碎片化,同时满足健康数据应用对跨端稳定性和数据一致性的严苛要求。
健康数据
健康数据聚合应用的核心价值在于数据的准确性和可分析性,代码中通过多层级的TypeScript类型定义构建了完整的健康数据领域模型,从基础用户信息到多维度健康指标、趋势分析数据,形成了闭环的数据体系,这不仅规避了前端开发中的类型错误,更在跨端编译阶段提前拦截了因平台数据格式差异导致的潜在问题。
// 核心用户档案模型
type User = {
id: string;
name: string;
age: number;
gender: string;
};
// 单条健康数据模型(核心指标维度)
type HealthData = {
id: string;
userId: string;
date: string;
steps: number; // 步数(整数型,保证数据精度)
heartRate: number; // 心率(bpm,医疗级数值精度)
sleepHours: number;// 睡眠时长(小时,支持小数)
};
// 趋势分析数据模型(时序数据集合)
type TrendData = {
id: string;
userId: string;
period: string; // 周期(周/月)
steps: number[]; // 步数时序数组
heartRate: number[];// 心率时序数组
sleepHours: number[];// 睡眠时序数组
};
这些类型定义严格约束了健康数据的格式和类型,所有数值型指标均采用number类型,避免了字符串转数值时的精度丢失问题。在鸿蒙系统中,React Native的TypeScript编译器会对JS层与鸿蒙ArkTS层之间的数据交互进行类型校验——例如步数、心率等核心指标在跨端传递时,会被强制校验为number类型,避免了因鸿蒙ArkTS的静态类型特性与JavaScript动态类型特性不兼容导致的运行时错误。值得注意的是,趋势数据采用数组类型存储时序数据,这种标准化的数据结构在鸿蒙系统中能够被高效序列化/反序列化,保证了周/月趋势分析功能在鸿蒙设备上的精准计算。
应用的核心业务逻辑基于React Hooks(useState、useEffect)实现,这种轻量级的状态管理方式完美适配React Native的跨端生命周期模型,同时与鸿蒙系统的组件生命周期形成深度映射,尤其适配了健康数据趋势自动生成这类周期性任务的需求。
生命周期
// 基础数据状态(不可变初始化)
const [users] = useState<User[]>([/* 初始化用户档案 */]);
const [healthData, setHealthData] = useState<HealthData[]>([/* 初始化健康数据 */]);
const [trendData, setTrendData] = useState<TrendData[]>([/* 初始化趋势数据 */]);
const [doctors] = useState<Doctor[]>([/* 初始化医生信息 */]);
// 交互与表单状态
const [selectedUser, setSelectedUser] = useState<string | null>(null);
const [newHealthData, setNewHealthData] = useState({
date: '', steps: '', heartRate: '', sleepHours: ''
});
useState负责管理组件内部的状态数据,其不可变的状态更新机制(如setHealthData([...healthData, newData]))保证了健康数据的一致性——每次添加新数据时,都会创建新的数组副本,而非修改原数组,这种设计在鸿蒙系统中能够避免因引用类型数据共享导致的状态混乱。而useEffect则承担了跨端生命周期管理的核心职责,代码中通过useEffect实现的趋势数据自动生成逻辑:
useEffect(() => {
const interval = setInterval(() => {
const randomUser = users[Math.floor(Math.random() * users.length)];
const newTrend: TrendData = {
id: (trendData.length + 1).toString(),
userId: randomUser.id,
period: '月',
steps: Array.from({ length: 30 }, () => Math.floor(Math.random() * 5000) + 5000),
heartRate: Array.from({ length: 30 }, () => Math.floor(Math.random() * 20) + 60),
sleepHours: Array.from({ length: 30 }, () => Math.floor(Math.random() * 3) + 6)
};
setTrendData(prevTrends => [...prevTrends, newTrend]);
}, 60000);
return () => clearInterval(interval);
}, [users, trendData]);
这段代码在鸿蒙系统中稳定运行的核心原因在于:setInterval/clearInterval是React Native封装的通用定时器API,已适配鸿蒙的任务调度机制;useEffect的返回清理函数则对应鸿蒙组件的onDestroy生命周期,确保定时器在组件卸载时被正确销毁,避免鸿蒙系统中的内存泄漏问题——这对需要长期运行、实时更新健康数据的应用尤为重要。同时,Array.from生成的时序数组采用标准化的数值生成逻辑,在鸿蒙设备上能够保证随机数生成的一致性,避免了不同平台随机数算法差异导致的趋势数据偏差。
UI组件
应用的UI层完全基于React Native的核心组件构建,样式通过StyleSheet.create统一管理,这种设计既保证了UI在鸿蒙系统中的无缝适配,又兼顾了健康数据应用对数据展示清晰性、操作便捷性的特殊要求。
样式系统
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f9ff', // 健康类应用专属浅蓝主题,适配鸿蒙视觉规范
},
section: {
backgroundColor: '#ffffff',
marginHorizontal: 16,
marginBottom: 12,
borderRadius: 12,
padding: 16,
// 阴影效果跨端适配:elevation适配鸿蒙/Android,shadow系列适配iOS
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
input: {
flex: 1,
backgroundColor: '#f0f9ff',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8,
fontSize: 14,
color: '#0c4a6e',
marginRight: 8,
},
// 按钮、卡片、弹窗等组件样式定义
});
StyleSheet将CSS样式抽象为跨平台的样式对象,在鸿蒙系统中,flex布局、padding/margin、borderRadius等核心样式属性会被精准转换为ArkUI的布局属性(如flexDirection、paddingLeft、borderRadius);针对步数、心率等数值型输入,TextInput组件设置keyboardType="numeric"属性,在鸿蒙设备上会自动唤起数字键盘,提升健康数据录入的准确性和便捷性。代码中通过Dimensions.get('window')获取屏幕尺寸:
const { width, height } = Dimensions.get('window');
该API在鸿蒙系统中能够准确获取设备的屏幕像素尺寸,避免了直接使用鸿蒙原生API(如getWindowSize)导致的代码碎片化,保证了不同屏幕尺寸鸿蒙设备(手机、平板、智慧手表)上的布局一致性——尤其适配了健康数据应用在鸿蒙多形态设备上的展示需求。
交互组件
核心交互逻辑基于TouchableOpacity组件实现,该组件在鸿蒙系统中会被渲染为具备点击反馈的原生按钮组件,保证了跨端交互体验的统一,同时其选中态的边框高亮样式(selectedCard)能够清晰标识当前操作的用户/医生,符合健康数据应用的操作指引要求:
<TouchableOpacity
style={[styles.card, selectedUser === user.id && styles.selectedCard]}
onPress={() => handleSelectUser(user.id)}
>
{/* 用户健康档案展示 */}
</TouchableOpacity>
Modal组件通过animationType="slide"实现滑动弹窗效果,在鸿蒙系统中适配为原生的滑动模态框,用于展示趋势数据的平均值计算结果(步数Avg、心率Avg、睡眠Avg),既保证了数据展示的完整性,又符合鸿蒙系统的交互规范。Alert.alert作为跨端通用弹窗API,在鸿蒙设备上调用原生弹窗组件,用于数据添加成功/失败、数据共享等关键操作的反馈,确保健康数据操作的结果提示及时且清晰。
当前代码已具备基础的鸿蒙兼容能力,在生产环境中可针对鸿蒙系统的特性和健康数据应用的特殊需求进行以下优化,进一步提升应用体验:
-
高性能时序数据渲染:当前趋势数据采用ScrollView + map的方式渲染,在鸿蒙系统中面对30天/90天的海量时序数据时可能出现卡顿。可替换为React Native的FlatList组件,该组件在鸿蒙系统中会适配ArkUI的List组件,实现按需渲染和组件复用,同时通过
getItemLayout优化列表滚动性能,尤其适合展示长周期的健康趋势数据。 -
鸿蒙原生健康能力集成:若需调用鸿蒙的健康原生能力(如从鸿蒙健康应用读取步数/心率数据、写入睡眠记录),可通过React Native的Native Module机制封装鸿蒙的Health Ability API,构建JS与ArkTS的通信桥梁——例如将应用中的健康数据同步到鸿蒙系统的健康中心,或从鸿蒙设备的传感器实时获取心率数据,在保留跨端代码架构的同时,充分利用鸿蒙系统的原生健康能力。
-
分布式数据共享优化:鸿蒙系统的核心特性是分布式能力,可基于React Native的跨端通信机制,实现健康数据在多鸿蒙设备(手机、平板、智慧屏)之间的分布式共享——例如在手机上录入的健康数据,可实时同步到鸿蒙平板的健康趋势分析界面,提升多设备使用场景下的用户体验。
这款基于React Native开发的健康数据聚合应用,通过TypeScript强类型约束、React Hooks状态管理、通用UI组件与样式设计,构建了具备完整鸿蒙跨端兼容能力的健康数据类应用架构。核心技术要点可总结为:
- 采用通用API+组件构建核心健康数据业务逻辑,规避平台专属代码,是实现鸿蒙兼容的基础,同时保证了健康数据的跨端一致性;
- TypeScript类型系统不仅提升健康数据的准确性,更在跨端编译阶段拦截数据类型错误,适配鸿蒙ArkTS的静态类型特性,避免医疗级数据的精度丢失;
- React Hooks的状态管理与鸿蒙组件生命周期深度适配,尤其满足了健康趋势数据自动生成等周期性任务的跨端稳定运行需求;
- 统一的StyleSheet样式系统实现了UI在鸿蒙设备上的一致性渲染,兼顾健康数据应用的视觉清晰性和操作便捷性。
基于该架构,只需少量针对鸿蒙原生健康能力的扩展和分布式数据共享优化,即可打造出体验优良的鸿蒙版健康数据聚合应用,为跨端健康管理类应用开发提供了可复用的技术范式。
在健康科技领域,数据驱动的健康管理正逐渐成为主流。本文将深入剖析一个基于 React Native 构建的健康数据聚合应用,探讨其技术实现细节及鸿蒙跨端能力的应用。
技术选型
该应用采用了现代 React Native 函数式组件架构,通过 TypeScript 类型系统和 React Hooks 实现了一个功能完整的健康数据管理系统。核心技术栈包括:
- React Native:作为跨端开发框架,提供了统一的组件 API,确保应用在 iOS、Android 及鸿蒙平台上的一致性体验
- TypeScript:通过严格的类型定义增强代码可维护性,明确了数据结构和组件接口
- React Hooks:使用 useState 管理应用状态,useEffect 处理副作用逻辑,实现了声明式的状态管理
- Base64 图标:采用 Base64 编码的图标资源,避免了不同平台资源格式的差异,提高了跨端兼容性
- 响应式布局:使用 Dimensions API 获取屏幕尺寸,实现适配不同设备的响应式界面
数据模型
应用通过 TypeScript 接口定义了四个核心数据类型,构建了完整的健康数据模型体系:
// 用户类型
type User = {
id: string;
name: string;
age: number;
gender: string;
};
// 健康数据类型
type HealthData = {
id: string;
userId: string;
date: string;
steps: number;
heartRate: number;
sleepHours: number;
};
// 趋势图数据类型
type TrendData = {
id: string;
userId: string;
period: string;
steps: number[];
heartRate: number[];
sleepHours: number[];
};
// 医生类型
type Doctor = {
id: string;
name: string;
specialty: string;
experience: string;
rating: number;
};
这种强类型设计不仅提高了代码可读性,也为鸿蒙跨端适配提供了清晰的数据契约,确保不同平台间数据传递的一致性。数据模型的设计充分考虑了健康监测的核心指标,包含了步数、心率、睡眠时长等关键健康数据,并通过趋势图数据类型实现了健康数据的可视化分析。
状态管理
应用使用 useState Hook 管理多个复杂状态,包括用户列表、健康数据、趋势数据、医生信息等:
const [users] = useState<User[]>([
{
id: '1',
name: '李先生',
age: 45,
gender: '男'
},
{
id: '2',
name: '王女士',
age: 32,
gender: '女'
}
]);
// 其他状态定义...
特别值得注意的是,应用通过 useEffect 实现了趋势图数据的自动生成机制:
// 自动生成趋势图数据
useEffect(() => {
const interval = setInterval(() => {
const randomUser = users[Math.floor(Math.random() * users.length)];
const newTrend: TrendData = {
id: (trendData.length + 1).toString(),
userId: randomUser.id,
period: '月',
steps: Array.from({ length: 30 }, () => Math.floor(Math.random() * 5000) + 5000),
heartRate: Array.from({ length: 30 }, () => Math.floor(Math.random() * 20) + 60),
sleepHours: Array.from({ length: 30 }, () => Math.floor(Math.random() * 3) + 6)
};
setTrendData(prevTrends => [...prevTrends, newTrend]);
}, 60000);
return () => clearInterval(interval);
}, [users, trendData]);
这种基于时间间隔的自动生成机制,模拟了真实场景中健康数据的持续采集和分析过程,为用户提供了全面的健康趋势分析。同时,通过 useEffect 的清理函数,确保了定时器在组件卸载时被正确清除,避免了内存泄漏。
在 React Native 鸿蒙跨端开发中,该应用体现了以下关键技术点:
- 组件兼容性:使用 React Native 核心组件(如 SafeAreaView、View、Text、TouchableOpacity、ScrollView、Modal 等),确保在鸿蒙系统上的兼容性
- 资源管理:通过 Base64 编码的图标资源,避免了不同平台资源格式的差异,提高了跨端部署的一致性
- 尺寸适配:使用 Dimensions API 获取屏幕尺寸,实现响应式布局,适应不同设备屏幕
- 状态管理:采用 React Hooks 进行状态管理,保持跨平台代码一致性
- 类型安全:TypeScript 类型定义确保了数据结构在不同平台间的一致性
- API 调用:使用 React Native 统一的 API 调用方式,如 Alert 组件,确保在鸿蒙平台上的正确显示
- 数据处理:使用 JavaScript 标准库(如 Array.from、Math.random 等)进行数据处理,确保在鸿蒙平台上的兼容性
1. 健康数据管理
应用实现了健康数据的添加和管理功能,用户可以记录每日步数、心率和睡眠时长:
const handleAddHealthData = () => {
if (newHealthData.date && newHealthData.steps && newHealthData.heartRate && newHealthData.sleepHours && selectedUser) {
const newData: HealthData = {
id: (healthData.length + 1).toString(),
userId: selectedUser,
date: newHealthData.date,
steps: parseInt(newHealthData.steps),
heartRate: parseInt(newHealthData.heartRate),
sleepHours: parseInt(newHealthData.sleepHours)
};
setHealthData([...healthData, newData]);
setNewHealthData({ date: '', steps: '', heartRate: '', sleepHours: '' });
Alert.alert('添加成功', '新的健康数据已添加');
} else {
Alert.alert('提示', '请选择用户并填写完整的健康数据');
}
};
2. 健康趋势分析
应用提供了健康趋势的查看功能,通过计算平均值等统计指标,为用户提供健康状况的整体分析:
const handleViewTrend = (trendId: string) => {
const trend = trendData.find(t => t.id === trendId);
if (trend) {
const user = users.find(u => u.id === trend.userId);
const stepsAvg = (trend.steps.reduce((a, b) => a + b, 0) / trend.steps.length).toFixed(2);
const heartRateAvg = (trend.heartRate.reduce((a, b) => a + b, 0) / trend.heartRate.length).toFixed(2);
const sleepHoursAvg = (trend.sleepHours.reduce((a, b) => a + b, 0) / trend.sleepHours.length).toFixed(2);
setModalContent(`用户: ${user?.name}\n周期: ${trend.period}\n平均步数: ${stepsAvg}\n平均心率: ${heartRateAvg}\n平均睡眠: ${sleepHoursAvg}小时`);
setIsModalVisible(true);
}
};
3. 数据共享功能
应用实现了健康数据的共享功能,用户可以将自己的健康数据共享给医生,便于远程诊断和指导:
const handleShareData = () => {
if (selectedDoctor && selectedUser) {
const doctor = doctors.find(d => d.id === selectedDoctor);
const user = users.find(u => u.id === selectedUser);
if (doctor && user) {
Alert.alert('数据共享', `已将${user.name}的健康数据共享给${doctor.name}医生`);
}
} else {
Alert.alert('提示', '请选择医生和用户');
}
};
4. 医生管理
应用集成了医生资源,用户可以选择专业医生进行健康指导,提高健康管理的专业性和有效性。
应用的 UI 设计遵循了现代移动应用的设计原则,使用了以下组件和交互模式:
- 安全区域:通过 SafeAreaView 确保内容显示在安全区域内,适应不同设备的屏幕刘海和底部指示条
- 滚动视图:通过 ScrollView 实现内容的垂直滚动,适应不同长度的健康数据列表和趋势分析
- 卡片布局:使用 TouchableOpacity 和 View 组合实现卡片式列表项,提供清晰的视觉层次和交互反馈
- 模态框:通过 Modal 组件展示详细信息,如健康趋势详情、数据共享结果等
- 交互反馈:使用 Alert 组件提供操作反馈和提示信息
- 响应式设计:根据屏幕尺寸动态调整布局,确保在不同设备上的良好显示效果
技术亮点与创新点
- 跨端架构:基于 React Native 构建,实现了一次编码多平台运行的目标,特别关注了鸿蒙平台的适配
- 类型安全:全面使用 TypeScript 类型定义,提高代码质量和可维护性,确保健康数据的准确性
- 健康数据聚合:实现了多维度健康数据的聚合和分析,包括步数、心率和睡眠时长
- 趋势分析:通过自动生成趋势图数据,为用户提供健康状况的长期趋势分析
- 数据共享:实现了健康数据与医生的安全共享,便于远程健康管理
- 实时数据反馈:通过即时的 Alert 反馈,增强用户操作体验
- 模块化设计:通过清晰的类型定义和函数划分,实现了代码的模块化,提高了可维护性
- 数据可视化基础:通过趋势数据的结构设计,为后续的健康数据可视化奠定了基础
在实际应用中,还可以考虑以下性能优化策略:
- 状态管理优化:对于大型应用,可以考虑使用 Redux 或 Context API 进行全局状态管理,提高状态更新的效率
- 组件拆分:将大型组件拆分为更小的可复用组件,提高渲染性能和代码可维护性
- 数据缓存:对用户数据和健康记录进行本地缓存,减少重复计算和网络请求
- 动画性能:使用 React Native 的 Animated API 实现流畅的过渡动画,提升用户体验
- 内存管理:确保及时清理不再使用的状态和事件监听器,避免内存泄漏
- 网络优化:对于实际应用中的远程数据同步,实现合理的网络请求策略,如批量上传、增量同步等
- 计算优化:对于健康数据的统计分析,如平均值计算,可以考虑使用 memoization 技术缓存计算结果
- 列表优化:对于长列表,使用 FlatList 组件替代 ScrollView,提高渲染性能
- 数据处理优化:对于大量健康数据的处理,考虑使用 Web Workers 或其他并行处理技术,避免阻塞主线程
在开发过程中,可能面临的技术挑战及解决方案:
- 鸿蒙平台适配:通过使用 React Native 核心组件和统一的 API 调用方式,确保应用在鸿蒙平台上的兼容性
- 健康数据同步:实现本地数据与云端数据的实时同步,确保多设备数据一致性
- 用户隐私保护:实现健康数据的加密存储和传输,保护用户隐私,符合健康数据安全法规
- 离线功能:实现基本的离线操作能力,确保在网络不稳定情况下的正常使用
- 性能优化:针对不同设备性能差异,实现自适应的性能优化策略,确保在中低端设备上的流畅运行
- 数据可视化:实现健康数据的可视化展示,如步数趋势图、心率变化曲线等
- 实时数据采集:与设备传感器集成,实现健康数据的实时采集,减少手动输入
- 用户体验一致性:确保在不同平台上的用户体验一致,特别是交互方式和视觉效果
通过对这个健康数据聚合应用的技术解读,我们可以看到 React Native 在跨端开发中的强大能力。该应用不仅实现了完整的健康数据管理功能,还展示了如何通过 TypeScript、React Hooks 等现代前端技术构建高质量的跨端应用。
在鸿蒙生态快速发展的今天,React Native 作为一种成熟的跨端解决方案,为健康科技应用提供了一种高效、统一的开发方式,使应用能够快速适配包括鸿蒙在内的多个平台。这种技术路线不仅降低了开发成本,也提高了应用的可维护性和扩展性,为健康管理领域的数字化转型带来了更多可能性。
未来,随着物联网技术的发展和智能穿戴设备的普及,类似的应用将会在个性化健康管理、远程医疗监控等领域发挥越来越重要的作用,为用户提供更加智能、全面的健康管理解决方案。通过持续的技术创新和功能迭代,这类应用有望成为人们日常健康管理的重要工具,帮助人们实现更健康的生活方式。
真实演示案例代码:
// App.tsx
import React, { useState, useEffect } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Dimensions, Alert, TextInput, Modal } from 'react-native';
// Base64 图标库
const ICONS_BASE64 = {
steps: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
heart: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
sleep: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
share: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};
const { width, height } = Dimensions.get('window');
// 用户类型
type User = {
id: string;
name: string;
age: number;
gender: string;
};
// 健康数据类型
type HealthData = {
id: string;
userId: string;
date: string;
steps: number;
heartRate: number;
sleepHours: number;
};
// 趋势图数据类型
type TrendData = {
id: string;
userId: string;
period: string;
steps: number[];
heartRate: number[];
sleepHours: number[];
};
// 医生类型
type Doctor = {
id: string;
name: string;
specialty: string;
experience: string;
rating: number;
};
// 健康数据聚合应用组件
const HealthDataAggregationApp: React.FC = () => {
const [users] = useState<User[]>([
{
id: '1',
name: '李先生',
age: 45,
gender: '男'
},
{
id: '2',
name: '王女士',
age: 32,
gender: '女'
}
]);
const [healthData, setHealthData] = useState<HealthData[]>([
{
id: '1',
userId: '1',
date: '2023-12-01',
steps: 8000,
heartRate: 72,
sleepHours: 7
},
{
id: '2',
userId: '1',
date: '2023-12-02',
steps: 10000,
heartRate: 68,
sleepHours: 8
}
]);
const [trendData, setTrendData] = useState<TrendData[]>([
{
id: '1',
userId: '1',
period: '周',
steps: [8000, 10000, 9500, 11000, 9000, 12000, 8500],
heartRate: [72, 68, 70, 69, 71, 67, 73],
sleepHours: [7, 8, 7.5, 8.5, 7.2, 8.8, 7.3]
}
]);
const [doctors] = useState<Doctor[]>([
{
id: '1',
name: '张医生',
specialty: '心血管内科',
experience: '10年经验',
rating: 4.8
},
{
id: '2',
name: '李医生',
specialty: '睡眠医学',
experience: '8年经验',
rating: 4.9
}
]);
const [selectedUser, setSelectedUser] = useState<string | null>(null);
const [selectedDoctor, setSelectedDoctor] = useState<string | null>(null);
const [newHealthData, setNewHealthData] = useState({
date: '',
steps: '',
heartRate: '',
sleepHours: ''
});
const [isModalVisible, setIsModalVisible] = useState(false);
const [modalContent, setModalContent] = useState('');
// 自动生成趋势图数据
useEffect(() => {
const interval = setInterval(() => {
const randomUser = users[Math.floor(Math.random() * users.length)];
const newTrend: TrendData = {
id: (trendData.length + 1).toString(),
userId: randomUser.id,
period: '月',
steps: Array.from({ length: 30 }, () => Math.floor(Math.random() * 5000) + 5000),
heartRate: Array.from({ length: 30 }, () => Math.floor(Math.random() * 20) + 60),
sleepHours: Array.from({ length: 30 }, () => Math.floor(Math.random() * 3) + 6)
};
setTrendData(prevTrends => [...prevTrends, newTrend]);
}, 60000);
return () => clearInterval(interval);
}, [users, trendData]);
const handleSelectUser = (userId: string) => {
setSelectedUser(userId);
Alert.alert('选择用户', '您已选择该用户进行健康数据分析');
};
const handleSelectDoctor = (doctorId: string) => {
setSelectedDoctor(doctorId);
Alert.alert('选择医生', '您已选择该医生进行数据共享');
};
const handleAddHealthData = () => {
if (newHealthData.date && newHealthData.steps && newHealthData.heartRate && newHealthData.sleepHours && selectedUser) {
const newData: HealthData = {
id: (healthData.length + 1).toString(),
userId: selectedUser,
date: newHealthData.date,
steps: parseInt(newHealthData.steps),
heartRate: parseInt(newHealthData.heartRate),
sleepHours: parseInt(newHealthData.sleepHours)
};
setHealthData([...healthData, newData]);
setNewHealthData({ date: '', steps: '', heartRate: '', sleepHours: '' });
Alert.alert('添加成功', '新的健康数据已添加');
} else {
Alert.alert('提示', '请选择用户并填写完整的健康数据');
}
};
const handleViewTrend = (trendId: string) => {
const trend = trendData.find(t => t.id === trendId);
if (trend) {
const user = users.find(u => u.id === trend.userId);
const stepsAvg = (trend.steps.reduce((a, b) => a + b, 0) / trend.steps.length).toFixed(2);
const heartRateAvg = (trend.heartRate.reduce((a, b) => a + b, 0) / trend.heartRate.length).toFixed(2);
const sleepHoursAvg = (trend.sleepHours.reduce((a, b) => a + b, 0) / trend.sleepHours.length).toFixed(2);
setModalContent(`用户: ${user?.name}\n周期: ${trend.period}\n平均步数: ${stepsAvg}\n平均心率: ${heartRateAvg}\n平均睡眠: ${sleepHoursAvg}小时`);
setIsModalVisible(true);
}
};
const handleShareData = () => {
if (selectedDoctor && selectedUser) {
const doctor = doctors.find(d => d.id === selectedDoctor);
const user = users.find(u => u.id === selectedUser);
if (doctor && user) {
Alert.alert('数据共享', `已将${user.name}的健康数据共享给${doctor.name}医生`);
}
} else {
Alert.alert('提示', '请选择医生和用户');
}
};
const openModal = (content: string) => {
setModalContent(content);
setIsModalVisible(true);
};
const closeModal = () => {
setIsModalVisible(false);
};
return (
<SafeAreaView style={styles.container}>
{/* 头部 */}
<View style={styles.header}>
<Text style={styles.title}>健康数据聚合</Text>
<Text style={styles.subtitle}>聚合步数、心率、睡眠等数据,生成周/月趋势图,支持与医生共享数据</Text>
</View>
<ScrollView style={styles.content}>
{/* 用户列表 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>用户列表</Text>
{users.map(user => (
<TouchableOpacity
key={user.id}
style={[
styles.card,
selectedUser === user.id && styles.selectedCard
]}
onPress={() => handleSelectUser(user.id)}
>
<Text style={styles.icon}>👤</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>{user.name}</Text>
<Text style={styles.cardDescription}>年龄: {user.age}</Text>
<Text style={styles.cardDescription}>性别: {user.gender}</Text>
</View>
</TouchableOpacity>
))}
</View>
{/* 健康数据录入 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>健康数据录入</Text>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
placeholder="日期 (YYYY-MM-DD)"
value={newHealthData.date}
onChangeText={(text) => setNewHealthData({ ...newHealthData, date: text })}
/>
<TextInput
style={styles.input}
placeholder="步数"
value={newHealthData.steps}
onChangeText={(text) => setNewHealthData({ ...newHealthData, steps: text })}
keyboardType="numeric"
/>
</View>
<View style={styles.inputRow}>
<TextInput
style={styles.input}
placeholder="心率 (bpm)"
value={newHealthData.heartRate}
onChangeText={(text) => setNewHealthData({ ...newHealthData, heartRate: text })}
keyboardType="numeric"
/>
<TextInput
style={styles.input}
placeholder="睡眠 (小时)"
value={newHealthData.sleepHours}
onChangeText={(text) => setNewHealthData({ ...newHealthData, sleepHours: text })}
keyboardType="numeric"
/>
</View>
<TouchableOpacity
style={styles.addButton}
onPress={handleAddHealthData}
>
<Text style={styles.addText}>添加健康数据</Text>
</TouchableOpacity>
</View>
{/* 趋势图 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>趋势图</Text>
{trendData.map(trend => (
<TouchableOpacity
key={trend.id}
style={styles.trendCard}
onPress={() => handleViewTrend(trend.id)}
>
<Text style={styles.icon}>📈</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>趋势ID: {trend.id}</Text>
<Text style={styles.cardDescription}>周期: {trend.period}</Text>
<Text style={styles.cardDescription}>步数趋势: {trend.steps.join(', ')}</Text>
<Text style={styles.cardDescription}>心率趋势: {trend.heartRate.join(', ')}</Text>
<Text style={styles.cardDescription}>睡眠趋势: {trend.sleepHours.join(', ')}</Text>
</View>
</TouchableOpacity>
))}
</View>
{/* 医生列表 */}
<View style={styles.section}>
<Text style={styles.sectionTitle}>医生列表</Text>
{doctors.map(doctor => (
<TouchableOpacity
key={doctor.id}
style={[
styles.card,
selectedDoctor === doctor.id && styles.selectedCard
]}
onPress={() => handleSelectDoctor(doctor.id)}
>
<Text style={styles.icon}>👨⚕️</Text>
<View style={styles.cardInfo}>
<Text style={styles.cardTitle}>{doctor.name}</Text>
<Text style={styles.cardDescription}>专长: {doctor.specialty}</Text>
<Text style={styles.cardDescription}>经验: {doctor.experience}</Text>
<Text style={styles.cardDescription}>评分: {doctor.rating}</Text>
</View>
</TouchableOpacity>
))}
<TouchableOpacity
style={styles.shareButton}
onPress={handleShareData}
>
<Text style={styles.shareText}>共享数据</Text>
</TouchableOpacity>
</View>
{/* 使用说明 */}
<View style={styles.infoCard}>
<Text style={styles.sectionTitle}>📘 使用说明</Text>
<Text style={styles.infoText}>• 选择用户进行健康数据管理</Text>
<Text style={styles.infoText}>• 录入每日步数、心率、睡眠数据</Text>
<Text style={styles.infoText}>• 查看生成的周/月趋势图</Text>
<Text style={styles.infoText}>• 与医生共享健康数据以获得专业建议</Text>
</View>
{/* 弹框内容 */}
<Modal
animationType="slide"
transparent={true}
visible={isModalVisible}
onRequestClose={closeModal}
>
<View style={styles.modalContainer}>
<View style={styles.modalContent}>
<Text style={styles.modalTitle}>详细信息</Text>
<Text style={styles.modalText}>{modalContent}</Text>
<TouchableOpacity
style={styles.closeButton}
onPress={closeModal}
>
<Text style={styles.closeButtonText}>关闭</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f0f9ff',
},
header: {
flexDirection: 'column',
padding: 16,
backgroundColor: '#ffffff',
borderBottomWidth: 1,
borderBottomColor: '#bae6fd',
},
title: {
fontSize: 20,
fontWeight: 'bold',
color: '#0c4a6e',
marginBottom: 4,
},
subtitle: {
fontSize: 14,
color: '#0284c7',
},
content: {
flex: 1,
marginTop: 12,
},
section: {
backgroundColor: '#ffffff',
marginHorizontal: 16,
marginBottom: 12,
borderRadius: 12,
padding: 16,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
sectionTitle: {
fontSize: 16,
fontWeight: '600',
color: '#0c4a6e',
marginBottom: 12,
},
card: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f9ff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
},
selectedCard: {
borderWidth: 2,
borderColor: '#0284c7',
},
trendCard: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#f0f9ff',
borderRadius: 12,
padding: 16,
marginBottom: 12,
},
icon: {
fontSize: 28,
marginRight: 12,
},
cardInfo: {
flex: 1,
},
cardTitle: {
fontSize: 16,
fontWeight: '500',
color: '#0c4a6e',
marginBottom: 4,
},
cardDescription: {
fontSize: 14,
color: '#0284c7',
marginBottom: 2,
},
inputRow: {
flexDirection: 'row',
justifyContent: 'space-between',
marginBottom: 12,
},
input: {
flex: 1,
backgroundColor: '#f0f9ff',
borderRadius: 8,
paddingHorizontal: 12,
paddingVertical: 8,
fontSize: 14,
color: '#0c4a6e',
marginRight: 8,
},
addButton: {
backgroundColor: '#0284c7',
padding: 12,
borderRadius: 8,
alignItems: 'center',
},
addText: {
color: '#ffffff',
fontSize: 14,
fontWeight: '500',
},
shareButton: {
backgroundColor: '#10b981',
padding: 16,
borderRadius: 12,
alignItems: 'center',
},
shareText: {
color: '#ffffff',
fontSize: 16,
fontWeight: '500',
},
infoCard: {
backgroundColor: '#ffffff',
marginHorizontal: 16,
marginBottom: 80,
borderRadius: 12,
padding: 16,
elevation: 2,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.1,
shadowRadius: 4,
},
infoText: {
fontSize: 14,
color: '#64748b',
lineHeight: 20,
marginBottom: 4,
},
modalContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
modalContent: {
width: '80%',
backgroundColor: '#ffffff',
borderRadius: 12,
padding: 20,
elevation: 5,
},
modalTitle: {
fontSize: 18,
fontWeight: 'bold',
color: '#0c4a6e',
marginBottom: 12,
textAlign: 'center',
},
modalText: {
fontSize: 14,
color: '#0c4a6e',
lineHeight: 20,
marginBottom: 20,
},
closeButton: {
backgroundColor: '#0284c7',
padding: 10,
borderRadius: 8,
alignItems: 'center',
},
closeButtonText: {
color: '#ffffff',
fontSize: 14,
fontWeight: '500',
},
});
export default HealthDataAggregationApp;

打包
接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

最后运行效果图如下显示:

本文深入解析了基于React Native开发的健康数据聚合应用跨端适配鸿蒙系统的关键技术。应用采用TypeScript构建严格类型约束的健康数据模型,确保多维度健康指标在跨端传递时的准确性。通过React Hooks实现状态管理与鸿蒙生命周期的深度映射,利用通用组件和样式系统保证UI在多形态鸿蒙设备上的展示一致性。核心在于"通用抽象层+平台适配层"的架构设计,避免了平台专属API导致的代码碎片化,使健康数据采集、趋势分析和跨端访问等功能在鸿蒙系统中稳定运行,为健康类应用的跨端开发提供了实践范例。
更多推荐


所有评论(0)