鸿蒙开发学习笔记 #6 - 分布式能力与高级特性
学习时间: 2026-03-14
主题: 分布式能力、高级特性、实战技巧
API 版本: HarmonyOS API 22+ (HarmonyOS NEXT/5.x)
---
1. 分布式能力概述
┌─────────────────────────────────────────────────────────────┐
│ 分布式能力架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 分布式数据管理 │ │
│ │ (跨设备数据同步) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 分布式任务调度 │ │
│ │ (跨设备启动能力) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 分布式文件访问 │ │
│ │ (跨设备文件共享) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
---
2. 分布式数据管理
2.1 基础概念
import distributedDataObject from '@ohos.data.distributedDataObject';
import deviceManager from '@ohos.distributedDeviceManager';
/**
* 分布式数据对象 (DDMO)
* 特点:
* - 自动跨设备同步
* - 实时监听数据变化
* - 支持复杂数据类型
*/
2.2 完整示例
/**
* 分布式数据管理器
*/
class DistributedDataManager {
private ddm: distributedDataObject.DataObject | null = null;
private deviceDm: deviceManager.DeviceManager | null = null;
private sessionId: string = '';
private isOnline: boolean = false;
/**
* 初始化分布式数据
*/
async init(context: any): Promise {
// 1. 创庺数据对象
this.ddm = distributedDataObject.create(context, {
name: 'user',
age: 25,
email: 'test@example.com'
});
// 2. 监听数据变化
this.ddm.on('change', (sessionId: string, fields: Array) => {
console.log('[DDM] 数据变化:', fields);
console.log('[DDM] 当前数据:', JSON.stringify(this.ddm));
});
// 3. 监听状态变化
this.ddm.on('status', (sessionId: string, networkId: string, status: string) => {
console.log('[DDM] 设备状态:', status, '设备:', networkId);
this.isOnline = status === 'online';
});
// 4. 获取设备管理器
this.deviceDm = deviceManager.getDeviceManager();
}
/**
* 加入分布式组网
*/
async joinGroup(networkId: string): Promise {
if (this.ddm) {
this.sessionId = networkId;
this.ddm.setSessionId(networkId);
console.log('[DDM] 已加入组网:', networkId);
}
}
/**
* 退出组网
*/
async leaveGroup(): Promise {
if (this.ddm && this.sessionId) {
this.ddm.setSessionId('');
this.sessionId = '';
console.log('[DDM] 已退出组网');
}
}
/**
* 修改数据 (自动同步)
*/
updateData(key: string, value: any): void {
if (this.ddm) {
(this.ddm as any)[key] = value;
console.log('[DDM] 数据已更新:', key, '=', value);
}
}
/**
* 获取数据
*/
getData(): any {
return this.ddm ? { ...(this.ddm as any) } : null;
}
/**
* 获取在线设备列表
*/
getOnlineDevices(): Array {
if (this.deviceDm) {
return this.deviceDm.getAvailableDeviceList();
}
return [];
}
/**
* 销毁
*/
destroy(): void {
if (this.ddm) {
this.ddm.off('change');
this.ddm.off('status');
this.ddm = null;
}
this.deviceDm = null;
}
}
---
3. 分布式任务调度
3.1 跨设备启动能力
import distributedScheduler from '@ohos.distributedScheduler';
import Want from '@ohos.app.ability.Want';
/**
* 分布式任务调度器
*/
class DistributedSchedulerManager {
/**
* 跨设备启动 Ability
*/
async startRemoteAbility(
deviceId: string,
bundleName: string,
abilityName: string,
params?: Record
): Promise {
const want: Want = {
bundleName: bundleName,
abilityName: abilityName,
parameters: params
};
try {
await distributedScheduler.startRemoteAbility(want, deviceId);
console.log('[DSS] 远程能力启动成功');
} catch (error) {
console.error('[DSS] 远程能力启动失败:', error);
throw error;
}
}
/**
* 跨设备迁移 UIAbility
*/
async migrateAbility(
sourceDeviceId: string,
targetDeviceId: string,
abilityName: string
): Promise {
const migrationInfo = {
sourceDeviceId: sourceDeviceId,
targetDeviceId: targetDeviceId,
abilityName: abilityName
};
try {
await distributedScheduler.migrateAbility(migrationInfo);
console.log('[DSS] 迁移成功');
} catch (error) {
console.error('[DSS] 迁移失败:', error);
}
}
/**
* 获取设备列表
*/
async getDeviceList(): Promise> {
// 获取可用设备
return [];
}
}
---
4. 常用工具类
4.1 日志工具
import hilog from '@ohos.hilog';
/**
* 日志工具
*/
class Logger {
private static domain: number = 0x0001; // 业务域
private static tag: string = 'MyApp';
private static isDebug: boolean = true;
static init(isDebug: boolean = true): void {
Logger.isDebug = isDebug;
}
static debug(message: string, ...args: any[]): void {
if (Logger.isDebug) {
hilog.debug(Logger.domain, Logger.tag, message, ...args);
}
}
static info(message: string, ...args: any[]): void {
hilog.info(Logger.domain, Logger.tag, message, ...args);
}
static warn(message: string, ...args: any[]): void {
hilog.warn(Logger.domain, Logger.tag, message, ...args);
}
static error(message: string, ...args: any[]): void {
hilog.error(Logger.domain, Logger.tag, message, ...args);
}
static perf(tag: string, startTime: number): void {
const duration = Date.now() - startTime;
Logger.info(`[PERF] ${tag}: ${duration}ms`);
}
}
// 使用
Logger.info('应用启动');
Logger.debug('用户登录:', username);
Logger.error('请求失败:', error.message);
4.2 日期格式化
/**
* 日期工具
*/
class DateUtils {
/**
* 格式化日期
*/
static format(date: Date, format: string = 'YYYY-MM-DD HH:mm:ss'): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hour = String(date.getHours()).padStart(2, '0');
const minute = String(date.getMinutes()).padStart(2, '0');
const second = String(date.getSeconds()).padStart(2, '0');
return format
.replace('YYYY', String(year))
.replace('MM', month)
.replace('DD', day)
.replace('HH', hour)
.replace('mm', minute)
.replace('ss', second);
}
/**
* 获取相对时间
*/
static getRelativeTime(timestamp: number): string {
const now = Date.now();
const diff = now - timestamp;
const minute = 60 * 1000;
const hour = 60 * minute;
const day = 24 * hour;
const week = 7 * day;
if (diff < minute) {
return '刚刚';
} else if (diff < hour) {
return `${Math.floor(diff / minute)}分钟前`;
} else if (diff < day) {
return `${Math.floor(diff / hour)}小时前`;
} else if (diff < week) {
return `${Math.floor(diff / day)}天前`;
} else {
return this.format(new Date(timestamp), 'YYYY-MM-DD');
}
}
/**
* 解析日期字符串
*/
static parse(dateString: string): Date | null {
try {
return new Date(dateString);
} catch {
return null;
}
}
}
4.3 对象工具
/**
* 对象工具
*/
class ObjectUtils {
/**
* 深拷贝
*/
static deepClone(obj: T): T {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime()) as any;
}
if (obj instanceof Array) {
const cloneArr: any[] = [];
obj.forEach((item) => {
cloneArr.push(this.deepClone(item));
});
return cloneArr as any;
}
if (obj instanceof Object) {
const cloneObj: any = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloneObj[key] = this.deepClone(obj[key]);
}
}
return cloneObj;
}
return obj;
}
/**
* 判断对象是否为空
*/
static isEmpty(obj: any): boolean {
if (obj === null || obj === undefined) {
return true;
}
if (typeof obj === 'string' || Array.isArray(obj)) {
return obj.length === 0;
}
if (typeof obj === 'object') {
return Object.keys(obj).length === 0;
}
return false;
}
/**
* 合并对象
*/
static merge(target: T, ...sources: Partial[]): T {
const result = { ...target };
sources.forEach(source => {
if (source) {
Object.keys(source).forEach(key => {
const value = (source as any)[key];
if (value !== undefined) {
(result as any)[key] = value;
}
});
}
});
return result;
}
}
4.4 字符串工具
/**
* 字符串工具
*/
class StringUtils {
/**
* 判断是否为空
*/
static isEmpty(str: string | null | undefined): boolean {
return !str || str.trim().length === 0;
}
/**
* 判断邮箱格式
*/
static isEmail(email: string): boolean {
const reg = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return reg.test(email);
}
/**
* 判断手机号
*/
static isPhone(phone: string): boolean {
const reg = /^1[3-9]\d{9}$/;
return reg.test(phone);
}
/**
* 脱敏手机号
*/
static maskPhone(phone: string): string {
if (phone.length !== 11) return phone;
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}
/**
* 脱敏身份证
*/
static maskIdCard(idCard: string): string {
if (idCard.length !== 18) return idCard;
return idCard.replace(/(\d{4})\d{10}(\d{4})/, '$1**********$2');
}
/**
* 截断字符串
*/
static truncate(str: string, maxLength: number, ellipsis: string = '...'): string {
if (str.length <= maxLength) return str;
return str.substring(0, maxLength - ellipsis.length) + ellipsis;
}
/**
* 格式化金额
*/
static formatMoney(amount: number): string {
return `¥${amount.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`;
}
}
---
5. 常见组件封装
5.1 加载状态组件
/**
* 加载状态组件
*/
@Component
export struct LoadingView {
@Prop message: string = '加载中...';
@Prop show: boolean = true;
build() {
if (this.show) {
Column({ space: 15 }) {
LoadingProgress()
.color('#1890ff')
.width(40)
.height(40)
Text(this.message)
.fontSize(14)
.fontColor('#666666')
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.backgroundColor('rgba(0, 0, 0, 0.3)')
}
}
}
5.2 空状态组件
/**
* 空状态组件
*/
@Component
export struct EmptyView {
@Prop image: Resource = $r('app.media.ic_empty');
@Prop message: string = '暂无数据';
@Prop actionText?: string;
onAction?: () => void;
build() {
Column({ space: 20 }) {
Image(this.image)
.width(120)
.height(120)
Text(this.message)
.fontSize(16)
.fontColor('#999999')
if (this.actionText && this.onAction) {
Button(this.actionText)
.type(ButtonType.Normal)
.backgroundColor('#1890ff')
.fontColor(Color.White)
.onClick(this.onAction)
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
5.3 错误状态组件
/**
* 错误状态组件
*/
@Component
export struct ErrorView {
@Prop message: string = '加载失败';
@Prop showRetry: boolean = true;
onRetry?: () => void;
build() {
Column({ space: 20 }) {
Image($r('app.media.ic_error'))
.width(80)
.height(80)
Text(this.message)
.fontSize(16)
.fontColor('#999999')
if (this.showRetry && this.onRetry) {
Button('点击重试')
.type(ButtonType.Normal)
.backgroundColor('#1890ff')
.fontColor(Color.White)
.onClick(this.onRetry)
}
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
5.4 确认对话框组件
/**
* 确认对话框
*/
@CustomDialog
struct ConfirmDialog {
@Prop title: string = '提示';
@Prop message: string = '';
@Prop confirmText: string = '确定';
@Prop cancelText: string = '取消';
@Prop confirmColor: string = '#1890ff';
controller: CustomDialogController;
onConfirm?: () => void;
onCancel?: () => void;
build() {
Column({ space: 20 }) {
Text(this.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(this.message)
.fontSize(14)
.fontColor('#666666')
.textAlign(TextAlign.Center)
Row({ space: 15 }) {
Button(this.cancelText)
.layoutWeight(1)
.backgroundColor('#f5f5f5')
.fontColor('#333333')
.onClick(() => {
this.controller.close();
this.onCancel?.();
})
Button(this.confirmText)
.layoutWeight(1)
.backgroundColor(this.confirmColor)
.fontColor(Color.White)
.onClick(() => {
this.controller.close();
this.onConfirm?.();
})
}
.height(44)
}
.width('80%')
.padding(20)
.backgroundColor(Color.White)
.borderRadius(12)
}
}
// 使用
showConfirm(): void {
const dialogController = new CustomDialogController({
builder: ConfirmDialog({
title: '确认删除',
message: '确定要删除这个项目吗?此操作不可恢复。',
onConfirm: () => {
// 执行删除
}
})
});
dialogController.open();
}
---
6. 最佳实践
6.1 代码组织规范
/**
* 推荐的代码组织结构
*/
// 1. 常量放顶部
const PAGE_SIZE = 20;
const API_BASE_URL = 'https://api.example.com';
// 2. 类型定义
interface User {
id: number;
name: string;
email: string;
}
// 3. 工具函数
function formatDate(date: Date): string {
return date.toISOString().split('T')[0];
}
// 4. 组件
@Component
struct MyComponent {
// 状态放前面
@State data: User[] = [];
// 生命周期
aboutToAppear(): void {
this.loadData();
}
// 业务方法
async loadData(): Promise {
// ...
}
// 构建方法
build() {
// ...
}
}
6.2 错误处理规范
/**
* 统一的错误处理
*/
// 1. 定义错误类型
enum ErrorCode {
NETWORK = -1,
TIMEOUT = -2,
SERVER = -3,
AUTH = 401,
PERMISSION = 403,
NOT_FOUND = 404
}
class AppError extends Error {
code: ErrorCode;
constructor(code: ErrorCode, message: string) {
super(message);
this.code = code;
this.name = 'AppError';
}
}
// 2. 统一的错误处理
function handleError(error: Error): string {
if (error instanceof AppError) {
switch (error.code) {
case ErrorCode.NETWORK:
return '网络连接失败,请检查网络';
case ErrorCode.TIMEOUT:
return '请求超时,请稍后重试';
case ErrorCode.AUTH:
return '登录已过期,请重新登录';
default:
return error.message;
}
}
return '未知错误';
}
// 3. 在组件中使用
@Component
struct UserPage {
@State error: string = '';
async loadData(): Promise {
try {
// 请求
} catch (error) {
this.error = handleError(error as Error);
}
}
}
6.3 性能优化检查清单
/**
* 性能优化检查清单
*/
// ✅ 列表使用 LazyForEach
// ✅ 大图使用 asyncLoad
// ✅ 合理使用 @State
// ✅ 及时释放资源 (aboutToDisappear)
// ✅ 避免在 build() 中创建对象
// ✅ 使用 @Concurrent 处理耗时任务
// ✅ 图片设置合适的 objectFit
// ✅ 减少不必要的状态更新
// ✅ 使用缓存减少重复计算
// ❌ 避免
// - build() 中做复杂计算
// - 频繁更新无关状态
// - 大对象直接传递给子组件
// - 不必要的深度监听
---
7. 学习资源汇总
7.1 官方文档
|------|------|
7.2 进阶学习方向
┌─────────────────────────────────────────────────────────────┐
│ 进阶学习方向 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 高级 UI 组件 │
│ - Canvas 绘图 │
│ - Web 组件 │
│ - 动画系统 │
│ │
│ ✅ AI 能力集成 │
│ - 语音识别 │
│ - 图像识别 │
│ - 机器学习 │
│ │
│ ✅ 鸿蒙生态开发 │
│ - 鸿蒙智联 (HarmonyOS Connect) │
│ - 服务卡片 (Service Widget) │
│ - 原子化服务 │
│ │
│ ✅ 工程实践 │
│ - 组件化架构 │
│ - CI/CD │
│ - 性能分析 │
│ │
└─────────────────────────────────────────────────────────────┘
---
📝 学习总结
✅ 已掌握技能
|------|------|------|
🚀 下一步
- 实战项目练习
- 鸿蒙生态开发 (卡片、服务)
- AI 能力集成
---
笔记完成!🎉
API 22+ 专用笔记 - 完整版
2026-03-14