【鸿蒙开发手册】重生之我要学习鸿蒙HarmonyOS开发
文章目录
- 引言
- 第一章:鸿蒙系统概述与发展历程
- 1.1 鸿蒙系统的诞生背景
- 1.1.1 技术发展趋势
- 1.1.2 市场需求驱动
- 1.2 鸿蒙系统的核心理念
- 1.2.1 一次开发,多端部署
- 1.2.2 分布式软总线
- 1.3 发展历程与版本演进
- 1.3.1 关键时间节点
- 1.3.2 技术能力演进
- 第二章:鸿蒙系统架构深度解析
- 2.1 分布式架构设计
- 2.1.1 分布式软总线架构
- 2.1.2 分布式数据管理
- 2.2 分层架构设计
- 2.2.1 内核层
- 2.2.2 系统服务层
- 2.2.3 框架层
- 2.2.4 应用层
- 2.3 ArkTS语言特性
- 2.3.1 TypeScript超集
- 2.3.2 声明式UI开发
- 第三章:鸿蒙开发环境搭建与配置
- 3.1 DevEco Studio安装配置
- 3.1.1 系统要求
- 3.1.2 安装步骤
- 3.2 SDK配置与管理
- 3.2.1 SDK组件说明
- 3.2.2 依赖管理
- 3.3 项目创建与结构分析
- 3.3.1 项目结构
- 3.3.2 核心配置文件
- 第四章:鸿蒙应用开发基础
- 4.1 UIAbility生命周期管理
- 4.1.1 生命周期概述
- 4.1.2 ServiceExtensionAbility服务组件
- 4.2 自定义组件开发
- 4.2.1 基础组件封装
- 4.3 状态管理
- 4.3.1 本地状态管理
- 4.4 页面路由与导航
- 4.4.1 基础路由配置
- 4.4.2 页面间数据传递
- 第五章:鸿蒙分布式特性开发
- 5.1 跨设备应用迁移
- 5.1.1 应用迁移基础
- 5.1.2 迁移状态保存与恢复
- 5.2 协同组件开发
- 5.2.1 分布式组件通信
- 5.2.2 实际应用示例
- 5.3 分布式文件系统
- 5.3.1 跨设备文件访问
- 第六章:性能优化与最佳实践
- 6.1 应用性能优化
- 6.1.1 启动性能优化
- 6.1.2 内存管理优化
- 6.2 UI渲染优化
- 6.2.1 列表性能优化
- 6.3 网络优化
- 6.3.1 请求优化和缓存策略
- 第七章:总结与展望
- 7.1 知识点总结
- 7.1.1 核心技术要点
- 7.1.2 开发最佳实践
- 7.2 技术扩展与深入学习
- 7.2.1 进阶技术方向
- 7.2.2 学习资源推荐
- 7.3 技术发展趋势与思考
- 7.3.1 行业发展趋势
- 7.3.2 技术挑战与机遇
- 7.4 实践建议与行动计划
- 7.4.1 学习路径建议
- 7.4.2 实践项目推荐
- 7.5 互动与交流
- 7.5.1 讨论话题
- 7.5.2 学习交流建议
引言
随着万物互联时代的到来,传统的操作系统已经无法满足多设备协同、跨平台互通的需求。华为鸿蒙HarmonyOS作为面向全场景的分布式操作系统,以其独特的分布式架构和全栈解决方案,正在重新定义智能设备的交互方式。本文将从系统架构、开发环境、应用开发、分布式特性、性能优化等多个维度,深入解析鸿蒙系统的核心技术和开发实践,帮助开发者全面掌握鸿蒙应用开发的精髓。
第一章:鸿蒙系统概述与发展历程
1.1 鸿蒙系统的诞生背景
1.1.1 技术发展趋势
鸿蒙系统的诞生源于对未来智能生态的深度思考。在5G、IoT、AI等技术快速发展的背景下,传统的单设备操作系统已经无法满足多设备协同的需求。
1.1.2 市场需求驱动
消费者对于设备间无缝连接、数据共享、协同工作的需求日益增长,这要求操作系统具备天然的分布式能力。
1.2 鸿蒙系统的核心理念
1.2.1 一次开发,多端部署
鸿蒙系统通过统一的开发框架,实现了真正的"一次开发,多端部署",大大降低了开发成本。
// 统一的组件开发模式
@Entry
@Component
struct MainPage {@State message: string = 'Hello HarmonyOS'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
}
1.2.2 分布式软总线
通过分布式软总线技术,实现设备间的无缝连接和资源共享。
1.3 发展历程与版本演进
1.3.1 关键时间节点
- 2019年8月:鸿蒙OS 1.0发布
- 2020年9月:鸿蒙OS 2.0发布
- 2021年6月:HarmonyOS 2正式商用
- 2022年7月:HarmonyOS 3.0发布
- 2023年8月:HarmonyOS 4.0发布
1.3.2 技术能力演进
每个版本都在分布式能力、开发工具、性能优化等方面有显著提升。
第二章:鸿蒙系统架构深度解析
2.1 分布式架构设计
2.1.1 分布式软总线架构
鸿蒙系统的核心是分布式软总线,它为设备间通信提供了统一的抽象层。
// 分布式设备发现示例
import deviceManager from '@ohos.distributedHardware.deviceManager';class DeviceDiscovery {private dmInstance: deviceManager.DeviceManager;async initDeviceManager() {try {this.dmInstance = deviceManager.createDeviceManager('com.example.app');// 监听设备状态变化this.dmInstance.on('deviceStateChange', (data) => {console.info('Device state changed:', data);this.handleDeviceStateChange(data);});// 开始设备发现this.startDeviceDiscovery();} catch (error) {console.error('Init device manager failed:', error);}}private startDeviceDiscovery() {const discoverParam = {subscribeId: 1,mode: 0xAA, // 主动发现模式medium: 2, // 自动选择媒介freq: 2, // 高频发现isSameAccount: false,isWakeRemote: true,capability: 0};this.dmInstance.startDeviceDiscovery(discoverParam);}private handleDeviceStateChange(data: any) {switch (data.action) {case deviceManager.DeviceStateChangeAction.READY:console.info('Device ready:', data.device.deviceName);break;case deviceManager.DeviceStateChangeAction.OFFLINE:console.info('Device offline:', data.device.deviceName);break;}}
}
2.1.2 分布式数据管理
通过分布式数据管理服务,实现数据在多设备间的同步和共享。
import distributedData from '@ohos.data.distributedData';class DistributedDataManager {private kvStore: distributedData.KVStore;async initKVStore() {const kvManagerConfig = {context: getContext(this),bundleName: 'com.example.app'};const kvManager = distributedData.createKVManager(kvManagerConfig);const options = {createIfMissing: true,encrypt: false,backup: false,autoSync: true,kvStoreType: distributedData.KVStoreType.DEVICE_COLLABORATION,schema: '',securityLevel: distributedData.SecurityLevel.S2};try {this.kvStore = await kvManager.getKVStore('user_preferences', options);this.setupSyncListener();} catch (error) {console.error('Create KV store failed:', error);}}private setupSyncListener() {this.kvStore.on('syncComplete', (data) => {console.info('Sync completed:', data);});}async syncData(key: string, value: string) {try {await this.kvStore.put(key, value);// 同步到其他设备const deviceList = await this.getConnectedDevices();if (deviceList.length > 0) {await this.kvStore.sync(deviceList, distributedData.SyncMode.PUSH_ONLY);}} catch (error) {console.error('Sync data failed:', error);}}private async getConnectedDevices(): Promise<string[]> {// 获取已连接的设备列表return [];}
}
2.2 分层架构设计
2.2.1 内核层
鸿蒙采用微内核架构,提供了更好的安全性和可靠性。
2.2.2 系统服务层
包含分布式软总线、分布式数据管理、分布式任务调度等核心服务。
2.2.3 框架层
提供应用开发所需的各种框架和API。
2.2.4 应用层
运行各种系统应用和第三方应用。
2.3 ArkTS语言特性
2.3.1 TypeScript超集
ArkTS是基于TypeScript的应用开发语言,提供了更强的类型安全和开发效率。
// 装饰器的使用
@Component
struct CustomButton {@Prop buttonText: string = 'Click Me'@Prop buttonColor: Color = Color.Blue@State isPressed: boolean = falsebuild() {Button(this.buttonText).backgroundColor(this.isPressed ? Color.Gray : this.buttonColor).onClick(() => {this.isPressed = !this.isPressedthis.handleClick()})}private handleClick() {console.info('Button clicked:', this.buttonText)}
}
2.3.2 声明式UI开发
采用声明式UI开发模式,让界面开发更加直观和高效。
@Entry
@Component
struct TodoList {@State todos: Array<TodoItem> = []@State inputText: string = ''build() {Column() {// 输入框Row() {TextInput({ placeholder: '添加新任务' }).layoutWeight(1).onChange((value: string) => {this.inputText = value})Button('添加').onClick(() => {this.addTodo()})}.padding(16)// 任务列表List() {ForEach(this.todos, (item: TodoItem, index: number) => {ListItem() {TodoItemComponent({ item: item,onToggle: () => this.toggleTodo(index),onDelete: () => this.deleteTodo(index)})}})}.layoutWeight(1)}.width('100%').height('100%')}private addTodo() {if (this.inputText.trim()) {this.todos.push({id: Date.now(),text: this.inputText,completed: false})this.inputText = ''}}private toggleTodo(index: number) {this.todos[index].completed = !this.todos[index].completed}private deleteTodo(index: number) {this.todos.splice(index, 1)}
}interface TodoItem {id: numbertext: stringcompleted: boolean
}
第三章:鸿蒙开发环境搭建与配置
3.1 DevEco Studio安装配置
3.1.1 系统要求
- Windows 10/11 (64位)
- macOS 10.15或更高版本
- Ubuntu 18.04或更高版本
- 内存:8GB以上推荐
- 存储:至少10GB可用空间
3.1.2 安装步骤
- 从华为开发者官网下载DevEco Studio
- 运行安装程序,选择安装路径
- 配置SDK路径和工具链
- 创建或导入项目
3.2 SDK配置与管理
3.2.1 SDK组件说明
{"apiVersion": 9,"version": {"code": 1000000,"name": "1.0.0"},"deviceConfig": {"default": {"debug": true}},"module": {"package": "com.example.myapplication","name": ".MyApplication","mainAbility": ".MainAbility","deviceType": ["phone","tablet","tv","wearable"],"distro": {"deliveryWithInstall": true,"moduleName": "entry","moduleType": "entry","installationFree": false},"abilities": [{"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}],"orientation": "unspecified","visible": true,"name": ".MainAbility","icon": "$media:icon","description": "$string:description_mainability","label": "$string:entry_MainAbility","type": "page","launchType": "standard"}]}
}
3.2.2 依赖管理
使用ohpm进行依赖包管理:
{"name": "my-harmony-app","version": "1.0.0","description": "A HarmonyOS application","main": "index.ets","author": "","license": "","dependencies": {"@ohos/hypium": "1.0.6"},"devDependencies": {"@ohos/hvigor-ohos-plugin": "1.4.6","@ohos/hvigor": "1.4.6"}
}
3.3 项目创建与结构分析
3.3.1 项目结构
MyApplication/
├── AppScope/
│ └── app.json5
├── entry/
│ ├── src/
│ │ ├── main/
│ │ │ ├── ets/
│ │ │ │ ├── entryability/
│ │ │ │ └── pages/
│ │ │ ├── resources/
│ │ │ └── module.json5
│ │ └── ohosTest/
│ ├── build-profile.json5
│ └── hvigorfile.ts
├── build-profile.json5
├── hvigorfile.ts
└── oh-package.json5
3.3.2 核心配置文件
app.json5配置:
{"app": {"bundleName": "com.example.myapplication","vendor": "example","versionCode": 1000000,"versionName": "1.0.0","icon": "$media:app_icon","label": "$string:app_name","distributedNotificationEnabled": true,"targetAPIVersion": 9}
}
module.json5配置:
{"module": {"name": "entry","type": "entry","description": "$string:module_desc","mainElement": "EntryAbility","deviceTypes": ["phone","tablet"],"deliveryWithInstall": true,"installationFree": false,"pages": "$profile:main_pages","abilities": [{"name": "EntryAbility","srcEntry": "./ets/entryability/EntryAbility.ts","description": "$string:EntryAbility_desc","icon": "$media:icon","label": "$string:EntryAbility_label","startWindowIcon": "$media:icon","startWindowBackground": "$color:start_window_background","exported": true,"skills": [{"entities": ["entity.system.home"],"actions": ["action.system.home"]}]}]}
}
第四章:鸿蒙应用开发基础
4.1 UIAbility生命周期管理
4.1.1 生命周期概述
UIAbility是鸿蒙应用的基本单元,具有完整的生命周期管理机制。
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';export default class EntryAbility extends UIAbility {onCreate(want, launchParam) {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');// 应用数据初始化this.initializeAppData();// 全局配置this.setupGlobalConfiguration();}onDestroy() {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');// 清理资源this.cleanup();}onWindowStageCreate(windowStage: window.WindowStage) {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');// 设置系统事件监听this.setupSystemEventListeners(windowStage);// 主窗口设置windowStage.loadContent('pages/Index', (err, data) => {if (err.code) {hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');return;}hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');});// 设置状态栏和导航栏this.setupStatusAndNavigationBar(windowStage);}onWindowStageDestroy() {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground() {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');// 应用进入前台时的处理this.handleAppForeground();}onBackground() {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');// 应用进入后台时的处理this.handleAppBackground();}private initializeAppData() {// 初始化应用数据console.info('Initializing app data...');}private setupGlobalConfiguration() {// 全局配置设置console.info('Setting up global configuration...');}private setupSystemEventListeners(windowStage: window.WindowStage) {// 系统事件监听设置console.info('Setting up system event listeners...');}private setupStatusAndNavigationBar(windowStage: window.WindowStage) {windowStage.getMainWindow().then((mainWindow) => {// 设置状态栏mainWindow.setWindowSystemBarEnable(['status', 'navigation']);// 设置状态栏样式mainWindow.setWindowSystemBarProperties({statusBarColor: '#FF0000FF',navigationBarColor: '#FF0000FF',statusBarContentColor: '#FFFFFF',navigationBarContentColor: '#FFFFFF'});});}private handleAppForeground() {// 应用状态管理console.info('App entered foreground');// 恢复定时任务this.resumePeriodicTasks();}private handleAppBackground() {// 应用状态管理console.info('App entered background');// 暂停定时任务this.pausePeriodicTasks();}private resumePeriodicTasks() {// 恢复周期性任务}private pausePeriodicTasks() {// 暂停周期性任务}private cleanup() {// 资源清理console.info('Cleaning up resources...');}
}
4.1.2 ServiceExtensionAbility服务组件
import ServiceExtensionAbility from '@ohos.app.ability.ServiceExtensionAbility';
import Want from '@ohos.app.ability.Want';
import rpc from '@ohos.rpc';class ServiceStub extends rpc.RemoteObject {constructor(des: string) {super(des);}onRemoteMessageRequest(code: number, data: rpc.MessageSequence, reply: rpc.MessageSequence, option: rpc.MessageOption) {console.info('ServiceStub onRemoteMessageRequest called');switch (code) {case 1: // 获取数据let result = this.getData();reply.writeString(result);break;case 2: // 设置数据let inputData = data.readString();this.setData(inputData);reply.writeInt(0); // 成功break;default:console.error('Unknown request code:', code);break;}return true;}private getData(): string {return 'Service data';}private setData(data: string) {console.info('Setting data:', data);}
}export default class BackgroundService extends ServiceExtensionAbility {private serviceStub: ServiceStub;onCreate(want: Want) {console.info('BackgroundService onCreate');this.serviceStub = new ServiceStub('BackgroundService');}onRequest(want: Want, startId: number) {console.info('BackgroundService onRequest');// 处理服务请求this.handleServiceRequest(want, startId);}onConnect(want: Want) {console.info('BackgroundService onConnect');return this.serviceStub;}onDisconnect(want: Want) {console.info('BackgroundService onDisconnect');}onDestroy() {console.info('BackgroundService onDestroy');}private handleServiceRequest(want: Want, startId: number) {// 根据want参数处理不同的服务请求const action = want.action;switch (action) {case 'com.example.START_BACKGROUND_TASK':this.startBackgroundTask();break;case 'com.example.STOP_BACKGROUND_TASK':this.stopBackgroundTask();break;default:console.warn('Unknown service action:', action);break;}}private startBackgroundTask() {console.info('Starting background task...');// 启动后台任务逻辑}private stopBackgroundTask() {console.info('Stopping background task...');// 停止后台任务逻辑}
}
4.2 自定义组件开发
4.2.1 基础组件封装
// 自定义卡片组件
@Component
export struct CustomCard {@Prop title: string = ''@Prop content: string = ''@Prop imageUrl: string = ''@Prop @Watch('onActionChanged') actionText: string = ''@State isExpanded: boolean = falseprivate onActionClick?: () => voidbuild() {Column() {// 卡片头部Row() {Text(this.title).fontSize(18).fontWeight(FontWeight.Bold).layoutWeight(1)Button(this.isExpanded ? '收起' : '展开').type(ButtonType.Normal).fontSize(12).onClick(() => {this.toggleExpanded()})}.width('100%').padding({ left: 16, right: 16, top: 12, bottom: 8 })// 图片区域if (this.imageUrl) {Image(this.imageUrl).width('100%').height(200).objectFit(ImageFit.Cover).borderRadius({ topLeft: 0, topRight: 0, bottomLeft: 8, bottomRight: 8 })}// 内容区域Column() {Text(this.content).fontSize(14).lineHeight(20).maxLines(this.isExpanded ? -1 : 3).textOverflow({ overflow: TextOverflow.Ellipsis }).width('100%')// 操作按钮if (this.actionText && this.onActionClick) {Button(this.actionText).width('100%').margin({ top: 12 }).onClick(() => {this.onActionClick?.()})}}.padding(16).alignItems(HorizontalAlign.Start)}.backgroundColor(Color.White).borderRadius(12).shadow({ radius: 8, color: '#1F000000', offsetX: 0, offsetY: 2 }).margin({ left: 16, right: 16, top: 8, bottom: 8 })}private toggleExpanded() {animateTo({duration: 300,curve: Curve.EaseInOut}, () => {this.isExpanded = !this.isExpanded})}onActionChanged() {console.info('Action text changed:', this.actionText)}// 组件方法public expand() {this.isExpanded = true}public collapse() {this.isExpanded = false}
}// 使用自定义组件
@Entry
@Component
struct CardDemo {@State cards: CardData[] = [{title: '鸿蒙开发指南',content: '鸿蒙系统是华为推出的面向全场景的分布式操作系统,具有强大的跨设备协同能力...',imageUrl: 'https://example.com/harmony-logo.png',actionText: '了解更多'},{title: 'ArkTS语言特性',content: 'ArkTS是基于TypeScript的声明式开发语言,为鸿蒙应用开发提供了强大的类型安全保障...',imageUrl: '',actionText: '查看详情'}]build() {Scroll() {Column() {ForEach(this.cards, (card: CardData, index: number) => {CustomCard({title: card.title,content: card.content,imageUrl: card.imageUrl,actionText: card.actionText,onActionClick: () => {this.handleCardAction(index)}})})}}.width('100%').height('100%').backgroundColor('#F5F5F5')}private handleCardAction(index: number) {console.info('Card action clicked:', index)// 处理卡片操作}
}interface CardData {title: stringcontent: stringimageUrl: stringactionText: string
}
4.3 状态管理
4.3.1 本地状态管理
// 状态管理类
class AppStateManager {private static instance: AppStateManagerprivate listeners: Map<string, Function[]> = new Map()private state: Map<string, any> = new Map()static getInstance(): AppStateManager {if (!AppStateManager.instance) {AppStateManager.instance = new AppStateManager()}return AppStateManager.instance}// 设置状态setState<T>(key: string, value: T) {const oldValue = this.state.get(key)this.state.set(key, value)// 通知监听者const keyListeners = this.listeners.get(key) || []keyListeners.forEach(listener => {listener(value, oldValue)})}// 获取状态getState<T>(key: string): T | undefined {return this.state.get(key)}// 订阅状态变化subscribe(key: string, listener: Function): () => void {if (!this.listeners.has(key)) {this.listeners.set(key, [])}const keyListeners = this.listeners.get(key)!keyListeners.push(listener)// 返回取消订阅函数return () => {const index = keyListeners.indexOf(listener)if (index > -1) {keyListeners.splice(index, 1)}}}// 批量更新状态batchUpdate(updates: Map<string, any>) {const affectedKeys = new Set<string>()// 更新所有状态updates.forEach((value, key) => {this.state.set(key, value)affectedKeys.add(key)})// 批量通知affectedKeys.forEach(key => {const keyListeners = this.listeners.get(key) || []const newValue = this.state.get(key)keyListeners.forEach(listener => {listener(newValue, undefined)})})}
}// 使用状态管理的组件
@Component
struct UserProfile {@State private userName: string = ''@State private userAvatar: string = ''@State private userLevel: number = 1private stateManager = AppStateManager.getInstance()private unsubscribers: (() => void)[] = []aboutToAppear() {// 订阅用户状态变化this.unsubscribers.push(this.stateManager.subscribe('userName', (newName: string) => {this.userName = newName}))this.unsubscribers.push(this.stateManager.subscribe('userAvatar', (newAvatar: string) => {this.userAvatar = newAvatar}))this.unsubscribers.push(this.stateManager.subscribe('userLevel', (newLevel: number) => {this.userLevel = newLevel}))// 初始化用户数据this.loadUserData()}aboutToDisappear() {// 取消所有订阅this.unsubscribers.forEach(unsubscribe => unsubscribe())this.unsubscribers = []}build() {Column() {// 用户头像Image(this.userAvatar || $r('app.media.default_avatar')).width(80).height(80).borderRadius(40).margin({ bottom: 16 })// 用户名Text(this.userName || '未登录').fontSize(20).fontWeight(FontWeight.Bold).margin({ bottom: 8 })// 用户等级Row() {Text('等级:').fontSize(14).fontColor('#666666')Text(this.userLevel.toString()).fontSize(14).fontColor('#FF6B35').fontWeight(FontWeight.Bold)}.margin({ bottom: 20 })// 操作按钮Button('更新资料').width('80%').onClick(() => {this.updateUserProfile()})}.width('100%').padding(20).alignItems(HorizontalAlign.Center)}private async loadUserData() {try {// 模拟从服务器加载用户数据const userData = await this.fetchUserData()// 批量更新状态const updates = new Map()updates.set('userName', userData.name)updates.set('userAvatar', userData.avatar)updates.set('userLevel', userData.level)this.stateManager.batchUpdate(updates)} catch (error) {console.error('Load user data failed:', error)}}private async fetchUserData(): Promise<UserData> {// 模拟网络请求return new Promise((resolve) => {setTimeout(() => {resolve({name: '鸿蒙开发者',avatar: 'https://example.com/avatar.jpg',level: 5})}, 1000)})}private updateUserProfile() {// 更新用户资料逻辑console.info('Updating user profile...')}
}interface UserData {name: stringavatar: stringlevel: number
}
4.4 页面路由与导航
4.4.1 基础路由配置
// router/index.ts
import router from '@ohos.router'export class RouterManager {private static instance: RouterManagerprivate routeStack: string[] = []static getInstance(): RouterManager {if (!RouterManager.instance) {RouterManager.instance = new RouterManager()}return RouterManager.instance}// 页面跳转async pushPage(url: string, params?: object): Promise<void> {try {await router.pushUrl({url: url,params: params})this.routeStack.push(url)console.info('Navigate to:', url)} catch (error) {console.error('Navigation failed:', error)throw error}}// 替换当前页面async replacePage(url: string, params?: object): Promise<void> {try {await router.replaceUrl({url: url,params: params})if (this.routeStack.length > 0) {this.routeStack[this.routeStack.length - 1] = url} else {this.routeStack.push(url)}console.info('Replace with:', url)} catch (error) {console.error('Replace failed:', error)throw error}}// 返回上一页async goBack(): Promise<void> {try {await router.back()if (this.routeStack.length > 0) {this.routeStack.pop()}console.info('Go back')} catch (error) {console.error('Go back failed:', error)throw error}}// 清空路由栈并跳转async clearAndPush(url: string, params?: object): Promise<void> {try {await router.clear()await this.pushPage(url, params)this.routeStack = [url]console.info('Clear and navigate to:', url)} catch (error) {console.error('Clear and push failed:', error)throw error}}// 获取当前路由栈getRouteStack(): string[] {return [...this.routeStack]}// 获取路由参数getParams<T>(): T | undefined {try {const params = router.getParams()return params as T} catch (error) {console.error('Get params failed:', error)return undefined}}
}// 页面基类
export abstract class BasePage {protected routerManager = RouterManager.getInstance()protected pageParams: anyaboutToAppear() {// 获取页面参数this.pageParams = this.routerManager.getParams()this.onPageLoad()}// 子类需要实现的方法protected abstract onPageLoad(): void// 通用导航方法protected navigateTo(url: string, params?: object) {this.routerManager.pushPage(url, params)}protected navigateBack() {this.routerManager.goBack()}protected navigateReplace(url: string, params?: object) {this.routerManager.replacePage(url, params)}
}
4.4.2 页面间数据传递
// 列表页面
@Entry
@Component
struct ProductList extends BasePage {@State products: Product[] = []@State loading: boolean = falseprotected onPageLoad() {this.loadProducts()}build() {Column() {// 标题栏Row() {Text('商品列表').fontSize(20).fontWeight(FontWeight.Bold).layoutWeight(1)Button('搜索').onClick(() => {this.navigateTo('pages/ProductSearch')})}.width('100%').padding(16).backgroundColor('#FFFFFF')// 商品列表if (this.loading) {LoadingIndicator()} else {List() {ForEach(this.products, (product: Product) => {ListItem() {ProductItem({product: product,onItemClick: (item: Product) => {this.navigateToDetail(item)}})}})}.layoutWeight(1)}}.width('100%').height('100%').backgroundColor('#F5F5F5')}private async loadProducts() {this.loading = truetry {// 模拟加载商品数据this.products = await this.fetchProducts()} catch (error) {console.error('Load products failed:', error)} finally {this.loading = false}}private navigateToDetail(product: Product) {this.navigateTo('pages/ProductDetail', {productId: product.id,productName: product.name,fromPage: 'ProductList'})}private async fetchProducts(): Promise<Product[]> {return new Promise((resolve) => {setTimeout(() => {resolve([{ id: 1, name: '华为Mate 50', price: 4999, image: 'mate50.jpg' },{ id: 2, name: '华为P60', price: 5999, image: 'p60.jpg' }])}, 1000)})}
}// 详情页面
@Entry
@Component
struct ProductDetail extends BasePage {@State product: Product | null = null@State loading: boolean = falseprivate productId: number = 0private fromPage: string = ''protected onPageLoad() {// 获取传递的参数if (this.pageParams) {this.productId = this.pageParams.productIdthis.fromPage = this.pageParams.fromPage}this.loadProductDetail()}build() {Column() {// 导航栏Row() {Button('返回').onClick(() => {this.handleBackPress()})Text('商品详情').fontSize(18).fontWeight(FontWeight.Bold).layoutWeight(1).textAlign(TextAlign.Center)Button('分享').onClick(() => {this.shareProduct()})}.width('100%').padding(16).backgroundColor('#FFFFFF')// 商品详情内容if (this.loading) {LoadingIndicator()} else if (this.product) {Scroll() {Column() {// 商品图片Image(this.product.image).width('100%').height(300).objectFit(ImageFit.Cover)// 商品信息Column() {Text(this.product.name).fontSize(20).fontWeight(FontWeight.Bold).margin({ bottom: 8 })Text(`¥${this.product.price}`).fontSize(24).fontColor('#FF6B35').fontWeight(FontWeight.Bold).margin({ bottom: 16 })// 操作按钮Row() {Button('加入购物车').layoutWeight(1).margin({ right: 8 }).onClick(() => {this.addToCart()})Button('立即购买').layoutWeight(1).margin({ left: 8 }).backgroundColor('#FF6B35').onClick(() => {this.buyNow()})}.width('100%')}.padding(16).alignItems(HorizontalAlign.Start)}}.layoutWeight(1)}}.width('100%').height('100%').backgroundColor('#F5F5F5')}private async loadProductDetail() {this.loading = truetry {this.product = await this.fetchProductDetail(this.productId)} catch (error) {console.error('Load product detail failed:', error)} finally {this.loading = false}}private handleBackPress() {// 可以根据来源页面做不同处理if (this.fromPage === 'ProductList') {this.navigateBack()} else {this.navigateTo('pages/ProductList')}}private shareProduct() {console.info('Share product:', this.product?.name)}private addToCart() {console.info('Add to cart:', this.product?.name)// 添加到购物车逻辑}private buyNow() {if (this.product) {this.navigateTo('pages/OrderConfirm', {product: this.product,quantity: 1})}}private async fetchProductDetail(id: number): Promise<Product> {return new Promise((resolve) => {setTimeout(() => {resolve({id: id,name: '华为Mate 50',price: 4999,image: 'https://example.com/mate50.jpg'})}, 800)})}
}// 商品项组件
@Component
struct ProductItem {@Prop product: Productprivate onItemClick?: (product: Product) => voidbuild() {Row() {Image(this.product.image).width(80).height(80).borderRadius(8).margin({ right: 12 })Column() {Text(this.product.name).fontSize(16).fontWeight(FontWeight.Medium).maxLines(2).textOverflow({ overflow: TextOverflow.Ellipsis }).margin({ bottom: 8 })Text(`¥${this.product.price}`).fontSize(18).fontColor('#FF6B35').fontWeight(FontWeight.Bold)}.layoutWeight(1).alignItems(HorizontalAlign.Start)}.width('100%').padding(16).backgroundColor('#FFFFFF').borderRadius(8).margin({ left: 16, right: 16, top: 8, bottom: 8 }).onClick(() => {this.onItemClick?.(this.product)})}
}// 加载指示器组件
@Component
struct LoadingIndicator {build() {Column() {LoadingProgress().width(50).height(50).margin({ bottom: 16 })Text('加载中...').fontSize(14).fontColor('#999999')}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}
}interface Product {id: numbername: stringprice: numberimage: string
}
第五章:鸿蒙分布式特性开发
5.1 跨设备应用迁移
5.1.1 应用迁移基础
import distributedMissionManager from '@ohos.distributedMissionManager';
import deviceManager from '@ohos.distributedHardware.deviceManager';class ApplicationMigrationManager {private dmInstance: deviceManager.DeviceManager;private currentMissionId: number = -1;async initMigrationCapability() {try {// 初始化设备管理器this.dmInstance = deviceManager.createDeviceManager('com.example.migration');// 监听设备状态变化this.dmInstance.on('deviceStateChange', (data) => {this.handleDeviceStateChange(data);});// 获取当前任务IDthis.currentMissionId = await this.getCurrentMissionId();console.info('Migration capability initialized');} catch (error) {console.error('Init migration capability failed:', error);}}// 开始应用迁移async startMigration(targetDeviceId: string, wantParam?: any) {try {const missionParam = {deviceId: targetDeviceId,missionId: this.currentMissionId,wantParam: wantParam || {}};// 执行迁移await distributedMissionManager.startSyncRemoteMissions(targetDeviceId, missionParam);console.info('Migration started to device:', targetDeviceId);// 保存迁移状态await this.saveMigrationState(targetDeviceId);} catch (error) {console.error('Start migration failed:', error);throw error;}}// 处理迁移回调async handleMigrationCallback(targetDeviceId: string, result: number) {if (result === 0) {console.info('Migration successful to:', targetDeviceId);// 迁移成功后的处理await this.onMigrationSuccess(targetDeviceId);} else {console.error('Migration failed with result:', result);// 迁移失败后的处理await this.onMigrationFailed(targetDeviceId, result);}}// 获取可迁移的设备列表async getAvailableDevices(): Promise<deviceManager.DeviceInfo[]> {try {const deviceList = this.dmInstance.getTrustedDeviceListSync();// 过滤支持迁移的设备return deviceList.filter(device => {return this.isDeviceSupportMigration(device);});} catch (error) {console.error('Get available devices failed:', error);return [];}}private async getCurrentMissionId(): Promise<number> {// 获取当前应用的任务IDreturn 1; // 示例值}private handleDeviceStateChange(data: any) {console.info('Device state changed:', data);if (data.action === deviceManager.DeviceStateChangeAction.READY) {console.info('Device ready for migration:', data.device.deviceName);}}private isDeviceSupportMigration(device: deviceManager.DeviceInfo): boolean {// 检查设备是否支持迁移return device.deviceType !== deviceManager.DeviceType.UNKNOWN;}private async saveMigrationState(targetDeviceId: string) {// 保存迁移状态到本地存储console.info('Saving migration state for device:', targetDeviceId);}private async onMigrationSuccess(targetDeviceId: string) {// 迁移成功后的清理工作console.info('Migration success cleanup for device:', targetDeviceId);}private async onMigrationFailed(targetDeviceId: string, errorCode: number) {// 迁移失败后的恢复工作console.error('Migration failed cleanup for device:', targetDeviceId, 'Error:', errorCode);}
}
5.1.2 迁移状态保存与恢复
// 应用状态管理器
class MigrationStateManager {private static readonly STATE_KEY = 'migration_state';private kvStore: distributedData.KVStore;async initStateManager() {const kvManagerConfig = {context: getContext(this),bundleName: 'com.example.migration'};const kvManager = distributedData.createKVManager(kvManagerConfig);const options = {createIfMissing: true,encrypt: false,backup: true,autoSync: true,kvStoreType: distributedData.KVStoreType.DEVICE_COLLABORATION,securityLevel: distributedData.SecurityLevel.S2};this.kvStore = await kvManager.getKVStore('migration_state', options);}// 保存应用状态async saveApplicationState(state: ApplicationState) {try {const stateJson = JSON.stringify(state);await this.kvStore.put(MigrationStateManager.STATE_KEY, stateJson);console.info('Application state saved');} catch (error) {console.error('Save application state failed:', error);}}// 恢复应用状态async restoreApplicationState(): Promise<ApplicationState | null> {try {const stateJson = await this.kvStore.get(MigrationStateManager.STATE_KEY) as string;if (stateJson) {const state = JSON.parse(stateJson) as ApplicationState;console.info('Application state restored');return state;}return null;} catch (error) {console.error('Restore application state failed:', error);return null;}}// 清除状态async clearApplicationState() {try {await this.kvStore.delete(MigrationStateManager.STATE_KEY);console.info('Application state cleared');} catch (error) {console.error('Clear application state failed:', error);}}
}// 支持迁移的页面基类
abstract class MigratablePage {protected migrationManager = new ApplicationMigrationManager();protected stateManager = new MigrationStateManager();async aboutToAppear() {await this.migrationManager.initMigrationCapability();await this.stateManager.initStateManager();// 检查是否需要恢复状态await this.checkAndRestoreState();}// 准备迁移async prepareMigration(): Promise<ApplicationState> {const state: ApplicationState = {pageUrl: this.getCurrentPageUrl(),pageData: await this.getPageData(),userInputs: this.getUserInputs(),scrollPosition: this.getScrollPosition(),timestamp: Date.now()};// 保存状态await this.stateManager.saveApplicationState(state);return state;}// 执行迁移async performMigration(targetDeviceId: string) {try {// 准备迁移状态const state = await this.prepareMigration();// 开始迁移await this.migrationManager.startMigration(targetDeviceId, {migrationState: state});} catch (error) {console.error('Perform migration failed:', error);throw error;}}// 检查并恢复状态private async checkAndRestoreState() {const state = await this.stateManager.restoreApplicationState();if (state) {console.info('Restoring application state:', state);await this.restorePageState(state);}}// 抽象方法,子类需要实现protected abstract getCurrentPageUrl(): string;protected abstract getPageData(): Promise<any>;protected abstract getUserInputs(): any;protected abstract getScrollPosition(): number;protected abstract restorePageState(state: ApplicationState): Promise<void>;
}interface ApplicationState {pageUrl: string;pageData: any;userInputs: any;scrollPosition: number;timestamp: number;
}
5.2 协同组件开发
5.2.1 分布式组件通信
// 分布式组件基类
abstract class DistributedComponent {protected deviceId: string = '';protected componentId: string = '';protected eventBus: DistributedEventBus;constructor(componentId: string) {this.componentId = componentId;this.eventBus = DistributedEventBus.getInstance();}async initDistributedCapability() {// 注册组件await this.eventBus.registerComponent(this.componentId, this);// 监听远程事件this.eventBus.on(`${this.componentId}_remote_event`, (data) => {this.handleRemoteEvent(data);});}// 发送事件到远程设备async sendEventToRemote(targetDeviceId: string, eventType: string, data: any) {await this.eventBus.sendToRemote(targetDeviceId, {componentId: this.componentId,eventType: eventType,data: data});}// 广播事件到所有设备async broadcastEvent(eventType: string, data: any) {await this.eventBus.broadcast({componentId: this.componentId,eventType: eventType,data: data});}// 处理远程事件protected abstract handleRemoteEvent(data: any): void;
}// 分布式事件总线
class DistributedEventBus {private static instance: DistributedEventBus;private components: Map<string, DistributedComponent> = new Map();private eventListeners: Map<string, Function[]> = new Map();private distributedObject: distributedObject.DistributedObject;static getInstance(): DistributedEventBus {if (!DistributedEventBus.instance) {DistributedEventBus.instance = new DistributedEventBus();}return DistributedEventBus.instance;}async init() {// 创建分布式对象this.distributedObject = distributedObject.createDistributedObject({events: new Map()});// 监听分布式对象变化this.distributedObject.on('change', (sessionId, fields) => {this.handleDistributedObjectChange(sessionId, fields);});}async registerComponent(componentId: string, component: DistributedComponent) {this.components.set(componentId, component);console.info('Component registered:', componentId);}on(eventType: string, listener: Function) {if (!this.eventListeners.has(eventType)) {this.eventListeners.set(eventType, []);}this.eventListeners.get(eventType)!.push(listener);}async sendToRemote(targetDeviceId: string, eventData: any) {try {// 通过分布式对象发送事件const eventKey = `${Date.now()}_${Math.random()}`;this.distributedObject.events.set(eventKey, {targetDeviceId: targetDeviceId,...eventData});console.info('Event sent to remote device:', targetDeviceId);} catch (error) {console.error('Send to remote failed:', error);}}async broadcast(eventData: any) {try {const eventKey = `broadcast_${Date.now()}_${Math.random()}`;this.distributedObject.events.set(eventKey, {broadcast: true,...eventData});console.info('Event broadcasted');} catch (error) {console.error('Broadcast failed:', error);}}private handleDistributedObjectChange(sessionId: string, fields: string[]) {fields.forEach(field => {if (field === 'events') {const events = this.distributedObject.events;events.forEach((eventData, eventKey) => {this.processRemoteEvent(eventData);});}});}private processRemoteEvent(eventData: any) {const { componentId, eventType } = eventData;const eventName = `${componentId}_remote_event`;const listeners = this.eventListeners.get(eventName) || [];listeners.forEach(listener => {listener(eventData);});}
}
5.2.2 实际应用示例
// 分布式音乐播放器组件
class DistributedMusicPlayer extends DistributedComponent {@State private currentSong: Song | null = null;@State private isPlaying: boolean = false;@State private progress: number = 0;@State private volume: number = 50;constructor() {super('music_player');}async aboutToAppear() {await this.initDistributedCapability();}build() {Column() {// 歌曲信息if (this.currentSong) {Column() {Image(this.currentSong.cover).width(200).height(200).borderRadius(12).margin({ bottom: 16 })Text(this.currentSong.title).fontSize(20).fontWeight(FontWeight.Bold).margin({ bottom: 8 })Text(this.currentSong.artist).fontSize(16).fontColor('#666666').margin({ bottom: 16 })}.alignItems(HorizontalAlign.Center)}// 进度条Row() {Text(this.formatTime(this.progress)).fontSize(12).fontColor('#999999')Slider({value: this.progress,min: 0,max: this.currentSong?.duration || 100,step: 1}).layoutWeight(1).margin({ left: 12, right: 12 }).onChange((value: number) => {this.seekTo(value);})Text(this.formatTime(this.currentSong?.duration || 0)).fontSize(12).fontColor('#999999')}.width('100%').margin({ bottom: 20 })// 控制按钮Row() {Button('上一首').onClick(() => {this.previousSong();})Button(this.isPlaying ? '暂停' : '播放').margin({ left: 16, right: 16 }).onClick(() => {this.togglePlayPause();})Button('下一首').onClick(() => {this.nextSong();})}.margin({ bottom: 20 })// 音量控制Row() {Text('音量').fontSize(14).margin({ right: 12 })Slider({value: this.volume,min: 0,max: 100,step: 1}).layoutWeight(1).onChange((value: number) => {this.setVolume(value);})}.width('100%').margin({ bottom: 20 })// 设备控制Button('同步到其他设备').width('80%').onClick(() => {this.syncToOtherDevices();})}.width('100%').padding(20).alignItems(HorizontalAlign.Center)}private togglePlayPause() {this.isPlaying = !this.isPlaying;// 同步播放状态到其他设备this.broadcastEvent('playStateChanged', {isPlaying: this.isPlaying,currentSong: this.currentSong,progress: this.progress});}private seekTo(position: number) {this.progress = position;// 同步进度到其他设备this.broadcastEvent('progressChanged', {progress: this.progress});}private setVolume(volume: number) {this.volume = volume;// 同步音量到其他设备this.broadcastEvent('volumeChanged', {volume: this.volume});}private previousSong() {// 切换到上一首歌曲的逻辑this.broadcastEvent('songChanged', {action: 'previous'});}private nextSong() {// 切换到下一首歌曲的逻辑this.broadcastEvent('songChanged', {action: 'next'});}private async syncToOtherDevices() {const currentState = {currentSong: this.currentSong,isPlaying: this.isPlaying,progress: this.progress,volume: this.volume};await this.broadcastEvent('fullStateSync', currentState);}protected handleRemoteEvent(data: any) {const { eventType, data: eventData } = data;switch (eventType) {case 'playStateChanged':this.isPlaying = eventData.isPlaying;this.currentSong = eventData.currentSong;this.progress = eventData.progress;break;case 'progressChanged':this.progress = eventData.progress;break;case 'volumeChanged':this.volume = eventData.volume;break;case 'songChanged':this.handleSongChange(eventData.action);break;case 'fullStateSync':this.currentSong = eventData.currentSong;this.isPlaying = eventData.isPlaying;this.progress = eventData.progress;this.volume = eventData.volume;break;}}private handleSongChange(action: string) {// 处理歌曲切换console.info('Handle song change:', action);}private formatTime(seconds: number): string {const mins = Math.floor(seconds / 60);const secs = Math.floor(seconds % 60);return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;}
}interface Song {id: string;title: string;artist: string;cover: string;duration: number;url: string;
}
5.3 分布式文件系统
5.3.1 跨设备文件访问
import distributedFile from '@ohos.file.distributedFile';
import fs from '@ohos.file.fs';class DistributedFileManager {private static instance: DistributedFileManager;static getInstance(): DistributedFileManager {if (!DistributedFileManager.instance) {DistributedFileManager.instance = new DistributedFileManager();}return DistributedFileManager.instance;}// 获取分布式文件路径async getDistributedFilePath(deviceId: string, bundleName: string, fileName: string): Promise<string> {try {const distributedPath = await distributedFile.getDistributedFilePath(deviceId, bundleName, fileName);console.info('Distributed file path:', distributedPath);return distributedPath;} catch (error) {console.error('Get distributed file path failed:', error);throw error;}}// 读取远程设备文件async readRemoteFile(deviceId: string, bundleName: string, fileName: string): Promise<string> {try {const filePath = await this.getDistributedFilePath(deviceId, bundleName, fileName);const file = fs.openSync(filePath, fs.OpenMode.READ_ONLY);const buffer = new ArrayBuffer(1024 * 1024); // 1MB bufferconst readResult = fs.readSync(file.fd, buffer);fs.closeSync(file);const content = String.fromCharCode.apply(null, new Uint8Array(buffer, 0, readResult));return content;} catch (error) {console.error('Read remote file failed:', error);throw error;}}// 写入文件到远程设备async writeRemoteFile(deviceId: string, bundleName: string, fileName: string, content: string): Promise<void> {try {const filePath = await this.getDistributedFilePath(deviceId, bundleName, fileName);const file = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.WRITE_ONLY);const buffer = new ArrayBuffer(content.length);const uint8Array = new Uint8Array(buffer);for (let i = 0; i < content.length; i++) {uint8Array[i] = content.charCodeAt(i);}fs.writeSync(file.fd, buffer);fs.closeSync(file);console.info('Write remote file success:', fileName);} catch (error) {console.error('Write remote file failed:', error);throw error;}}// 同步文件到多个设备async syncFileToDevices(fileName: string, content: string, targetDevices: string[]): Promise<void> {const bundleName = 'com.example.app';const syncPromises = targetDevices.map(deviceId => this.writeRemoteFile(deviceId, bundleName, fileName, content));try {await Promise.all(syncPromises);console.info('File synced to all devices:', fileName);} catch (error) {console.error('Sync file to devices failed:', error);throw error;}}// 获取文件列表async getRemoteFileList(deviceId: string, bundleName: string, dirPath: string): Promise<FileInfo[]> {try {const distributedDirPath = await distributedFile.getDistributedFilePath(deviceId, bundleName, dirPath);const files = fs.listFileSync(distributedDirPath);const fileInfoList: FileInfo[] = [];for (const fileName of files) {const filePath = `${distributedDirPath}/${fileName}`;const stat = fs.statSync(filePath);fileInfoList.push({name: fileName,path: filePath,size: stat.size,isDirectory: stat.isDirectory(),modifiedTime: stat.mtime});}return fileInfoList;} catch (error) {console.error('Get remote file list failed:', error);return [];}}// 删除远程文件async deleteRemoteFile(deviceId: string, bundleName: string, fileName: string): Promise<void> {try {const filePath = await this.getDistributedFilePath(deviceId, bundleName, fileName);fs.unlinkSync(filePath);console.info('Remote file deleted:', fileName);} catch (error) {console.error('Delete remote file failed:', error);throw error;}}
}// 分布式文件浏览器组件
@Component
struct DistributedFileBrowser {@State private fileList: FileInfo[] = [];@State private currentPath: string = '';@State private selectedDeviceId: string = '';@State private loading: boolean = false;private fileManager: DistributedFileManager = DistributedFileManager.getInstance();build() {Column() {// 设备选择Row() {Text('设备:').fontSize(16).margin({ right: 8 })Button(this.selectedDeviceId || '选择设备').layoutWeight(1).onClick(() => {this.showDeviceSelector();})}.width('100%').padding(16)// 当前路径if (this.currentPath) {Text(`路径:${this.currentPath}`).fontSize(14).fontColor('#666666').width('100%').padding({ left: 16, right: 16, bottom: 8 })}// 文件列表if (this.loading) {LoadingIndicator()} else {List() {ForEach(this.fileList, (file: FileInfo) => {ListItem() {FileItem({fileInfo: file,onItemClick: (item: FileInfo) => {this.handleFileClick(item);},onDeleteClick: (item: FileInfo) => {this.deleteFile(item);}})}})}.layoutWeight(1)}// 操作按钮Row() {Button('刷新').layoutWeight(1).margin({ right: 8 }).onClick(() => {this.refreshFileList();})Button('上传文件').layoutWeight(1).margin({ left: 8 }).onClick(() => {this.uploadFile();})}.width('100%').padding(16)}.width('100%').height('100%')}private async loadFileList() {if (!this.selectedDeviceId) {return;}this.loading = true;try {this.fileList = await this.fileManager.getRemoteFileList(this.selectedDeviceId,'com.example.app',this.currentPath || '/');} catch (error) {console.error('Load file list failed:', error);} finally {this.loading = false;}}private showDeviceSelector() {// 显示设备选择器console.info('Show device selector');}private handleFileClick(file: FileInfo) {if (file.isDirectory) {this.currentPath = file.path;this.loadFileList();} else {this.openFile(file);}}private async openFile(file: FileInfo) {try {const content = await this.fileManager.readRemoteFile(this.selectedDeviceId,'com.example.app',file.name);console.info('File content:', content);// 处理文件内容} catch (error) {console.error('Open file failed:', error);}}private async deleteFile(file: FileInfo) {try {await this.fileManager.deleteRemoteFile(this.selectedDeviceId,'com.example.app',file.name);// 刷新文件列表await this.loadFileList();} catch (error) {console.error('Delete file failed:', error);}}private refreshFileList() {this.loadFileList();}private uploadFile() {// 上传文件逻辑console.info('Upload file');}
}@Component
struct FileItem {@Prop fileInfo: FileInfo;private onItemClick?: (file: FileInfo) => void;private onDeleteClick?: (file: FileInfo) => void;build() {Row() {// 文件图标Image(this.fileInfo.isDirectory ? $r('app.media.folder_icon') : $r('app.media.file_icon')).width(32).height(32).margin({ right: 12 })// 文件信息Column() {Text(this.fileInfo.name).fontSize(16).fontWeight(FontWeight.Medium).alignSelf(ItemAlign.Start).margin({ bottom: 4 })Row() {Text(this.formatFileSize(this.fileInfo.size)).fontSize(12).fontColor('#999999').margin({ right: 16 })Text(this.formatDate(this.fileInfo.modifiedTime)).fontSize(12).fontColor('#999999')}.alignSelf(ItemAlign.Start)}.layoutWeight(1).alignItems(HorizontalAlign.Start)// 删除按钮Button('删除').fontSize(12).backgroundColor('#FF4444').onClick(() => {this.onDeleteClick?.(this.fileInfo);})}.width('100%').padding(16).backgroundColor('#FFFFFF').borderRadius(8).margin({ left: 16, right: 16, top: 4, bottom: 4 }).onClick(() => {this.onItemClick?.(this.fileInfo);})}private formatFileSize(size: number): string {if (size < 1024) {return `${size} B`;} else if (size < 1024 * 1024) {return `${(size / 1024).toFixed(1)} KB`;} else {return `${(size / (1024 * 1024)).toFixed(1)} MB`;}}private formatDate(timestamp: number): string {const date = new Date(timestamp);return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')}`;}
}interface FileInfo {name: string;path: string;size: number;isDirectory: boolean;modifiedTime: number;
}
第六章:性能优化与最佳实践
6.1 应用性能优化
6.1.1 启动性能优化
// 应用启动优化管理器
class AppStartupOptimizer {private static instance: AppStartupOptimizer;private preloadTasks: Map<string, () => Promise<void>> = new Map();private criticalResources: string[] = [];static getInstance(): AppStartupOptimizer {if (!AppStartupOptimizer.instance) {AppStartupOptimizer.instance = new AppStartupOptimizer();}return AppStartupOptimizer.instance;}// 注册预加载任务registerPreloadTask(taskName: string, task: () => Promise<void>) {this.preloadTasks.set(taskName, task);}// 注册关键资源registerCriticalResource(resourcePath: string) {this.criticalResources.push(resourcePath);}// 执行启动优化async optimizeStartup() {const startTime = Date.now();try {// 并行预加载关键资源await this.preloadCriticalResources();// 执行预加载任务await this.executePreloadTasks();// 初始化缓存await this.initializeCache();const endTime = Date.now();console.info(`Startup optimization completed in ${endTime - startTime}ms`);} catch (error) {console.error('Startup optimization failed:', error);}}private async preloadCriticalResources() {const preloadPromises = this.criticalResources.map(async (resourcePath) => {try {// 预加载图片资源if (resourcePath.endsWith('.png') || resourcePath.endsWith('.jpg')) {await this.preloadImage(resourcePath);}// 预加载字体资源else if (resourcePath.endsWith('.ttf') || resourcePath.endsWith('.otf')) {await this.preloadFont(resourcePath);}// 预加载数据else if (resourcePath.endsWith('.json')) {await this.preloadData(resourcePath);}} catch (error) {console.error(`Failed to preload resource: ${resourcePath}`, error);}});await Promise.all(preloadPromises);}private async executePreloadTasks() {const taskPromises = Array.from(this.preloadTasks.entries()).map(async ([taskName, task]) => {try {await task();console.info(`Preload task completed: ${taskName}`);} catch (error) {console.error(`Preload task failed: ${taskName}`, error);}});await Promise.all(taskPromises);}private async preloadImage(imagePath: string) {// 图片预加载逻辑console.info('Preloading image:', imagePath);}private async preloadFont(fontPath: string) {// 字体预加载逻辑console.info('Preloading font:', fontPath);}private async preloadData(dataPath: string) {// 数据预加载逻辑console.info('Preloading data:', dataPath);}private async initializeCache() {// 初始化应用缓存console.info('Initializing cache');}
}// 在应用入口使用启动优化
export default class EntryAbility extends UIAbility {private startupOptimizer: AppStartupOptimizer = AppStartupOptimizer.getInstance();onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {console.info('[EntryAbility] onCreate');// 注册关键资源this.startupOptimizer.registerCriticalResource('app.media.logo');this.startupOptimizer.registerCriticalResource('app.media.background');this.startupOptimizer.registerCriticalResource('resources/base/profile/main_pages.json');// 注册预加载任务this.startupOptimizer.registerPreloadTask('initUserData', async () => {await this.initializeUserData();});this.startupOptimizer.registerPreloadTask('initNetworkConfig', async () => {await this.initializeNetworkConfig();});}onWindowStageCreate(windowStage: window.WindowStage) {console.info('[EntryAbility] onWindowStageCreate');// 执行启动优化this.startupOptimizer.optimizeStartup().then(() => {// 加载主页面windowStage.loadContent('pages/Index', (err, data) => {if (err.code) {console.error('Failed to load the content:', JSON.stringify(err));return;}console.info('Succeeded in loading the content:', JSON.stringify(data));});});}private async initializeUserData() {// 初始化用户数据console.info('Initializing user data');}private async initializeNetworkConfig() {// 初始化网络配置console.info('Initializing network config');}
}
6.1.2 内存管理优化
// 内存管理器
class MemoryManager {private static instance: MemoryManager;private imageCache: Map<string, ImageBitmap> = new Map();private dataCache: Map<string, any> = new Map();private maxCacheSize: number = 50 * 1024 * 1024; // 50MBprivate currentCacheSize: number = 0;static getInstance(): MemoryManager {if (!MemoryManager.instance) {MemoryManager.instance = new MemoryManager();}return MemoryManager.instance;}// 缓存图片cacheImage(key: string, image: ImageBitmap, size: number) {if (this.currentCacheSize + size > this.maxCacheSize) {this.evictLRUCache(size);}this.imageCache.set(key, image);this.currentCacheSize += size;console.info(`Image cached: ${key}, size: ${size}, total: ${this.currentCacheSize}`);}// 获取缓存图片getCachedImage(key: string): ImageBitmap | null {return this.imageCache.get(key) || null;}// 缓存数据cacheData(key: string, data: any) {const size = this.calculateDataSize(data);if (this.currentCacheSize + size > this.maxCacheSize) {this.evictLRUCache(size);}this.dataCache.set(key, {data: data,timestamp: Date.now(),size: size});this.currentCacheSize += size;}// 获取缓存数据getCachedData(key: string): any {const cached = this.dataCache.get(key);if (cached) {// 更新访问时间cached.timestamp = Date.now();return cached.data;}return null;}// LRU缓存淘汰private evictLRUCache(requiredSize: number) {const allEntries = Array.from(this.dataCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);let freedSize = 0;for (const [key, value] of allEntries) {this.dataCache.delete(key);freedSize += value.size;this.currentCacheSize -= value.size;if (freedSize >= requiredSize) {break;}}console.info(`Evicted ${freedSize} bytes from cache`);}// 计算数据大小private calculateDataSize(data: any): number {return JSON.stringify(data).length * 2; // 粗略估算}// 清理缓存clearCache() {this.imageCache.clear();this.dataCache.clear();this.currentCacheSize = 0;console.info('Cache cleared');}// 获取内存使用情况getMemoryUsage(): MemoryUsage {return {totalCacheSize: this.currentCacheSize,maxCacheSize: this.maxCacheSize,imageCount: this.imageCache.size,dataCount: this.dataCache.size,usagePercentage: (this.currentCacheSize / this.maxCacheSize) * 100};}
}// 内存监控组件
@Component
struct MemoryMonitor {@State private memoryUsage: MemoryUsage = {totalCacheSize: 0,maxCacheSize: 0,imageCount: 0,dataCount: 0,usagePercentage: 0};private memoryManager: MemoryManager = MemoryManager.getInstance();private timer: number = -1;aboutToAppear() {this.updateMemoryUsage();this.timer = setInterval(() => {this.updateMemoryUsage();}, 5000); // 每5秒更新一次}aboutToDisappear() {if (this.timer !== -1) {clearInterval(this.timer);}}build() {Column() {Text('内存使用监控').fontSize(18).fontWeight(FontWeight.Bold).margin({ bottom: 16 })// 内存使用进度条Row() {Text('缓存使用率:').fontSize(14).margin({ right: 8 })Progress({value: this.memoryUsage.usagePercentage,total: 100,type: ProgressType.Linear}).layoutWeight(1).margin({ right: 8 })Text(`${this.memoryUsage.usagePercentage.toFixed(1)}%`).fontSize(12).fontColor('#666666')}.width('100%').margin({ bottom: 12 })// 详细信息Column() {this.createInfoRow('总缓存大小', this.formatBytes(this.memoryUsage.totalCacheSize))this.createInfoRow('最大缓存大小', this.formatBytes(this.memoryUsage.maxCacheSize))this.createInfoRow('图片缓存数量', this.memoryUsage.imageCount.toString())this.createInfoRow('数据缓存数量', this.memoryUsage.dataCount.toString())}.alignItems(HorizontalAlign.Start).margin({ bottom: 16 })// 操作按钮Button('清理缓存').width('100%').onClick(() => {this.memoryManager.clearCache();this.updateMemoryUsage();})}.width('100%').padding(16).backgroundColor('#F5F5F5').borderRadius(8)}@BuildercreateInfoRow(label: string, value: string) {Row() {Text(label).fontSize(14).fontColor('#333333').layoutWeight(1)Text(value).fontSize(14).fontColor('#666666')}.width('100%').margin({ bottom: 8 })}private updateMemoryUsage() {this.memoryUsage = this.memoryManager.getMemoryUsage();}private formatBytes(bytes: number): string {if (bytes < 1024) {return `${bytes} B`;} else if (bytes < 1024 * 1024) {return `${(bytes / 1024).toFixed(1)} KB`;} else {return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;}}
}interface MemoryUsage {totalCacheSize: number;maxCacheSize: number;imageCount: number;dataCount: number;usagePercentage: number;
}
6.2 UI渲染优化
6.2.1 列表性能优化
// 虚拟列表组件
@Component
struct VirtualList {@Prop items: any[];@Prop itemHeight: number = 60;@Prop containerHeight: number = 400;@State private visibleItems: any[] = [];@State private scrollOffset: number = 0;private visibleCount: number = 0;private startIndex: number = 0;private endIndex: number = 0;aboutToAppear() {this.visibleCount = Math.ceil(this.containerHeight / this.itemHeight) + 2;this.updateVisibleItems();}build() {Column() {Scroll() {Column() {// 顶部占位if (this.startIndex > 0) {Blank().height(this.startIndex * this.itemHeight)}// 可见项目ForEach(this.visibleItems, (item: any, index: number) => {ListItem() {this.itemBuilder(item, this.startIndex + index)}.height(this.itemHeight)})// 底部占位if (this.endIndex < this.items.length - 1) {Blank().height((this.items.length - this.endIndex - 1) * this.itemHeight)}}}.height(this.containerHeight).onScroll((xOffset: number, yOffset: number) => {this.scrollOffset = yOffset;this.updateVisibleItems();})}}@BuilderitemBuilder(item: any, index: number) {Row() {Text(`Item ${index}: ${item.title || item.name || item}`).fontSize(16).layoutWeight(1).padding(16)}.width('100%').backgroundColor('#FFFFFF').borderRadius(4).margin({ bottom: 1 })}private updateVisibleItems() {this.startIndex = Math.floor(this.scrollOffset / this.itemHeight);this.endIndex = Math.min(this.startIndex + this.visibleCount, this.items.length - 1);this.visibleItems = this.items.slice(this.startIndex, this.endIndex + 1);}
}// 优化的图片加载组件
@Component
struct OptimizedImage {@Prop src: string;@Prop width: number = 100;@Prop height: number = 100;@Prop placeholder?: string;@State private loaded: boolean = false;@State private error: boolean = false;private memoryManager: MemoryManager = MemoryManager.getInstance();build() {Stack() {if (this.error) {// 错误占位符Column() {Image($r('app.media.error_icon')).width(32).height(32).margin({ bottom: 8 })Text('加载失败').fontSize(12).fontColor('#999999')}.justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).width(this.width).height(this.height).backgroundColor('#F0F0F0')} else if (!this.loaded) {// 加载占位符Column() {if (this.placeholder) {Image(this.placeholder).width(this.width).height(this.height).objectFit(ImageFit.Cover)} else {Column() {Image($r('app.media.loading_icon')).width(24).height(24).margin({ bottom: 8 })Text('加载中...').fontSize(12).fontColor('#999999')}.justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).width(this.width).height(this.height).backgroundColor('#F0F0F0')}}} else {// 实际图片Image(this.src).width(this.width).height(this.height).objectFit(ImageFit.Cover).onComplete(() => {this.loaded = true;this.error = false;}).onError(() => {this.loaded = false;this.error = true;})}}}aboutToAppear() {this.preloadImage();}private async preloadImage() {try {// 检查缓存const cached = this.memoryManager.getCachedImage(this.src);if (cached) {this.loaded = true;return;}// 预加载图片const image = new Image();image.onload = () => {this.loaded = true;this.error = false;// 缓存图片const size = this.width * this.height * 4; // 估算大小this.memoryManager.cacheImage(this.src, image as any, size);};image.onerror = () => {this.loaded = false;this.error = true;};image.src = this.src;} catch (error) {console.error('Preload image failed:', error);this.error = true;}}
}
6.3 网络优化
6.3.1 请求优化和缓存策略
// 网络请求优化管理器
class NetworkOptimizer {private static instance: NetworkOptimizer;private requestCache: Map<string, CachedResponse> = new Map();private pendingRequests: Map<string, Promise<any>> = new Map();private retryConfig: RetryConfig = {maxRetries: 3,retryDelay: 1000,backoffMultiplier: 2};static getInstance(): NetworkOptimizer {if (!NetworkOptimizer.instance) {NetworkOptimizer.instance = new NetworkOptimizer();}return NetworkOptimizer.instance;}// 优化的HTTP请求async request(options: RequestOptions): Promise<any> {const cacheKey = this.generateCacheKey(options);// 检查缓存if (options.cache && this.isCacheValid(cacheKey)) {console.info('Returning cached response for:', options.url);return this.requestCache.get(cacheKey)!.data;}// 检查是否有相同的请求正在进行if (this.pendingRequests.has(cacheKey)) {console.info('Reusing pending request for:', options.url);return this.pendingRequests.get(cacheKey)!;}// 创建新请求const requestPromise = this.executeRequest(options);this.pendingRequests.set(cacheKey, requestPromise);try {const response = await requestPromise;// 缓存响应if (options.cache) {this.cacheResponse(cacheKey, response, options.cacheTimeout || 300000); // 默认5分钟}return response;} finally {this.pendingRequests.delete(cacheKey);}}private async executeRequest(options: RequestOptions): Promise<any> {let lastError: Error | null = null;for (let attempt = 0; attempt <= this.retryConfig.maxRetries; attempt++) {try {const response = await this.performHttpRequest(options);if (response.responseCode === 200) {return JSON.parse(response.result.toString());} else {throw new Error(`HTTP ${response.responseCode}: ${response.result}`);}} catch (error) {lastError = error as Error;if (attempt < this.retryConfig.maxRetries) {const delay = this.retryConfig.retryDelay * Math.pow(this.retryConfig.backoffMultiplier, attempt);console.warn(`Request failed, retrying in ${delay}ms. Attempt ${attempt + 1}/${this.retryConfig.maxRetries}`);await this.delay(delay);}}}throw lastError;}private async performHttpRequest(options: RequestOptions): Promise<any> {return new Promise((resolve, reject) => {const httpRequest = http.createHttp();httpRequest.request(options.url, {method: options.method || http.RequestMethod.GET,header: options.headers || {},extraData: options.data}, (err, data) => {if (err) {reject(err);} else {resolve(data);}httpRequest.destroy();});});}private generateCacheKey(options: RequestOptions): string {const keyData = {url: options.url,method: options.method || 'GET',data: options.data};return JSON.stringify(keyData);}private isCacheValid(cacheKey: string): boolean {const cached = this.requestCache.get(cacheKey);if (!cached) {return false;}return Date.now() < cached.expireTime;}private cacheResponse(cacheKey: string, data: any, timeout: number) {this.requestCache.set(cacheKey, {data: data,expireTime: Date.now() + timeout});}private delay(ms: number): Promise<void> {return new Promise(resolve => setTimeout(resolve, ms));}// 批量请求优化async batchRequest(requests: RequestOptions[]): Promise<any[]> {const batchSize = 5; // 并发限制const results: any[] = [];for (let i = 0; i < requests.length; i += batchSize) {const batch = requests.slice(i, i + batchSize);const batchPromises = batch.map(request => this.request(request));try {const batchResults = await Promise.all(batchPromises);results.push(...batchResults);} catch (error) {console.error('Batch request failed:', error);throw error;}}return results;}// 清理过期缓存cleanExpiredCache() {const now = Date.now();const expiredKeys: string[] = [];this.requestCache.forEach((cached, key) => {if (now >= cached.expireTime) {expiredKeys.push(key);}});expiredKeys.forEach(key => {this.requestCache.delete(key);});console.info(`Cleaned ${expiredKeys.length} expired cache entries`);}
}interface RequestOptions {url: string;method?: string;headers?: Record<string, string>;data?: any;cache?: boolean;cacheTimeout?: number;
}interface CachedResponse {data: any;expireTime: number;
}interface RetryConfig {maxRetries: number;retryDelay: number;backoffMultiplier: number;
}
第七章:总结与展望
7.1 知识点总结
通过本文的深入学习,我们全面掌握了鸿蒙HarmonyOS开发的核心技术和实践方法:
7.1.1 核心技术要点
-
系统架构理解
- 分布式软总线架构的设计理念
- 分层架构中各层的职责和交互
- ArkTS语言的特性和优势
- 声明式UI开发范式
-
开发环境掌握
- DevEco Studio的安装和配置
- SDK管理和版本控制
- 项目创建和结构分析
- 调试和测试工具使用
-
应用开发基础
- UIAbility生命周期管理
- ServiceExtensionAbility服务开发
- 自定义组件设计
- 状态管理和数据绑定
- 页面路由和导航
-
分布式特性开发
- 跨设备应用迁移
- 协同组件通信
- 分布式文件系统访问
- 设备发现和连接管理
-
性能优化实践
- 应用启动性能优化
- 内存管理和缓存策略
- UI渲染性能提升
- 网络请求优化
7.1.2 开发最佳实践
-
代码组织
- 模块化设计原则
- 组件复用策略
- 状态管理模式
- 错误处理机制
-
性能考虑
- 懒加载和预加载平衡
- 内存使用监控
- 网络请求合并
- 缓存策略设计
-
用户体验
- 响应式设计
- 加载状态提示
- 错误友好提示
- 无障碍访问支持
7.2 技术扩展与深入学习
7.2.1 进阶技术方向
-
分布式数据管理
- 分布式数据库设计
- 数据同步策略
- 冲突解决机制
- 数据安全和隐私保护
-
AI能力集成
- 机器学习模型集成
- 语音识别和合成
- 图像处理和识别
- 自然语言处理
-
IoT设备连接
- 智能家居设备控制
- 传感器数据采集
- 设备状态监控
- 自动化场景配置
-
企业级应用开发
- 大型应用架构设计
- 微服务集成
- 安全认证和授权
- 数据分析和报表
7.2.2 学习资源推荐
-
官方文档和资源
- HarmonyOS开发者官网
- DevEco Studio用户指南
-
社区和论坛
- HarmonyOS开发者社区
- 华为开发者联盟
- GitHub开源项目
- Stack Overflow相关标签
-
实践项目建议
- 个人任务管理应用
- 智能家居控制中心
- 多设备协同笔记应用
- 分布式音视频播放器
7.3 技术发展趋势与思考
7.3.1 行业发展趋势
-
万物互联时代
- 设备连接数量爆发式增长
- 跨设备协同需求增强
- 边缘计算能力提升
- 5G网络普及加速
-
AI原生应用
- 智能化功能成为标配
- 个性化体验需求增长
- 自然交互方式普及
- 预测性服务兴起
-
隐私和安全
- 数据保护法规完善
- 用户隐私意识提高
- 零信任安全架构
- 端侧计算重要性增强
7.3.2 技术挑战与机遇
-
技术挑战
- 设备碎片化问题
- 网络延迟和稳定性
- 电池续航优化
- 开发复杂度增加
-
发展机遇
- 新兴应用场景涌现
- 开发工具不断完善
- 生态系统日趋成熟
- 市场需求持续增长
7.4 实践建议与行动计划
7.4.1 学习路径建议
-
基础阶段(1-2个月)
- 熟悉ArkTS语法和特性
- 掌握基本组件使用
- 完成简单应用开发
- 理解应用生命周期
-
进阶阶段(2-3个月)
- 深入分布式特性开发
- 掌握性能优化技巧
- 学习复杂状态管理
- 实践企业级应用开发
-
专家阶段(3-6个月)
- 参与开源项目贡献
- 设计复杂应用架构
- 分享技术经验
- 探索前沿技术应用
7.4.2 实践项目推荐
-
入门项目
// 待办事项管理应用 // 功能:任务创建、编辑、删除、状态管理 // 技术点:基础组件、状态管理、本地存储
-
进阶项目
// 多设备协同笔记应用 // 功能:实时同步、离线编辑、富文本支持 // 技术点:分布式数据、冲突解决、UI优化
-
高级项目
// 智能家居控制中心 // 功能:设备发现、远程控制、场景自动化 // 技术点:IoT集成、AI能力、安全认证
7.5 互动与交流
7.5.1 讨论话题
-
技术选型讨论
- 在什么场景下选择HarmonyOS开发?
- 如何平衡功能丰富性和性能表现?
- 分布式特性的最佳应用场景是什么?
-
开发经验分享
- 你在HarmonyOS开发中遇到的最大挑战是什么?
- 有哪些提高开发效率的技巧和工具?
- 如何设计用户友好的分布式应用体验?
-
未来发展预测
- HarmonyOS生态系统的发展前景如何?
- 哪些新兴技术会与HarmonyOS深度融合?
- 开发者应该重点关注哪些技术方向?
7.5.2 学习交流建议
-
加入技术社区
- 参与官方开发者社区讨论
- 关注技术博客和公众号
- 参加线上线下技术分享会
- 加入相关技术交流群
-
实践分享
- 记录学习笔记和心得
- 分享项目开发经验
- 贡献开源代码和文档
- 帮助其他开发者解决问题
-
持续学习
- 关注官方技术更新
- 学习相关前沿技术
- 参与技术认证考试
- 建立个人技术品牌
结语
鸿蒙HarmonyOS作为面向万物互联时代的操作系统,为开发者提供了前所未有的技术机遇。通过本文的学习,相信你已经掌握了HarmonyOS开发的核心技术和实践方法。
技术的学习是一个持续的过程,希望你能够:
- 🔖 收藏本文,作为学习和开发的参考资料
- 👍 点赞支持,让更多开发者看到这些有价值的内容
- 💬 积极讨论,在评论区分享你的学习心得和实践经验
- 🚀 持续实践,将所学知识应用到实际项目中
让我们一起在HarmonyOS的技术道路上不断前行,共同构建更加智能、互联的数字世界!
本文涵盖了HarmonyOS开发的核心技术点,包含大量实用代码示例。如果你觉得有帮助,请不要忘记点赞收藏,也欢迎在评论区分享你的学习心得和项目经验!