diff --git a/zh-cn/application-dev/ui/Readme-CN.md b/zh-cn/application-dev/ui/Readme-CN.md index 13210d677636ddc478d81aec25587aeb1635e8d6..4eb8b0fe32b85c758bd11537ccc09a3ce06ad8c2 100755 --- a/zh-cn/application-dev/ui/Readme-CN.md +++ b/zh-cn/application-dev/ui/Readme-CN.md @@ -202,7 +202,11 @@ - [属性修改器 (AttributeModifier)](arkts-user-defined-extension-attributeModifier.md) - [属性更新器 (AttributeUpdater)](arkts-user-defined-extension-attributeUpdater.md) - [自定义绘制修改器 (DrawModifier)](arkts-user-defined-extension-drawModifier.md) - - [使用镜像能力](arkts-mirroring-display.md) + - UI国际化 + - [UI国际化概述](ui-internationalization-overview.md) + - [使用镜像能力](arkts-mirroring-display.md) + - [UI国际化资源配置](ui-internationalization-resource-config.md) + - [UI国际化配置变更](ui-internationalization-configuration-changes.md) - 无障碍与适老化 - [支持无障碍](arkts-universal-attributes-accessibility.md) - [支持适老化](arkui-support-for-aging-adaptation.md) @@ -218,6 +222,8 @@ - [跨进程应用能力扩展(UIExtension,仅对系统应用开放)](arkts-ui-extension-components.md) - [跨线程嵌入式组件 (IsolatedComponent,仅对系统应用开放)](arkts-isolated-components.md) + - UI开发调优 + - [调试](ui-debugging.md) - 使用NDK接口构建UI - [NDK接口概述](ndk-build-ui-overview.md) - [接入ArkTS页面](ndk-access-the-arkts-page.md) diff --git a/zh-cn/application-dev/ui/arkui-overview.md b/zh-cn/application-dev/ui/arkui-overview.md index 22a34df2b1b59f77223d688965c462d2e83d4ad8..78618bb6d11354e3278a753176448e596c66576f 100644 --- a/zh-cn/application-dev/ui/arkui-overview.md +++ b/zh-cn/application-dev/ui/arkui-overview.md @@ -11,6 +11,104 @@ ArkUI(方舟UI框架)为应用的UI开发提供了完整的基础设施, - **组件:** UI构建与显示的最小单位,如列表、网格、按钮、单选框、进度条、文本等。开发者通过多种组件的组合,构建出满足自身应用诉求的完整界面。 +## 分层API架构 + +ArkUI框架的API体系采用分层设计,便于开发者根据业务复杂度和性能需求灵活选型。主要分为: +- **声明式API层**:面向绝大多数业务UI开发,提供高效、简洁的声明式UI描述能力。 +- **命令式API层**:适用于需要精细控制UI、与底层能力交互的场景。 +- **自定义扩展层**:为有特殊UI、性能或渲染需求的开发者提供自定义节点、扩展、渲染等高级能力。 +- **底层渲染与运行时**:由ArkUI引擎、ArkCompiler和ArkRuntime等组成,负责UI渲染、状态管理和跨平台适配。 + +``` +[声明式API] [命令式API] [自定义扩展] + \ | / + [ArkUI渲染引擎/运行时] +``` + +## API选型建议 + +ArkUI推荐开发者优先采用声明式API进行UI开发,因其开发效率高、代码简洁、易维护。命令式API适合对UI有特殊控制需求的场景,如动画、底层交互等。自定义能力则适用于需要突破框架默认能力、实现特殊渲染或性能优化的高级场景。 + +- **声明式API**:适合大多数业务UI开发,推荐为主选型。 +- **命令式API**:适合需要动态、细粒度控制UI的场景。 +- **自定义能力**:适合有特殊UI、性能或渲染需求的场景。 +- **类Web范式/混合开发**:适合Web前端迁移、兼容性需求等。 + +## 声明式API概述 + +声明式API是ArkUI的主推开发范式,基于ArkTS语言扩展,开发者通过接近自然语言的方式描述UI结构、状态和交互,无需关心底层渲染细节。 + +**优势:** +- 代码简洁、开发高效 +- 数据驱动UI变化,易于维护 +- 适合绝大多数业务UI场景 + +**典型场景:** +- 普通应用界面、表单、列表、动画、交互等 + +**示例:** +```ts +@Entry +@Component +struct Index { + @State count: number = 0; + build() { + Column() { + Text(`${this.count}`) + Button("+").onClick(() => this.count++) + } + } +} +``` + +## 命令式API概述 + +命令式API适用于需要对UI进行精细、动态控制的场景,开发者可通过命令式调用直接操作UI元素、动画、底层能力等。 + +**适用场景:** +- 复杂动画、底层交互、与系统能力深度集成 +- 需要动态创建/销毁UI元素、响应复杂事件 + +**与声明式区别:** +- 声明式关注"描述是什么",命令式关注"如何做" +- 命令式更灵活,但代码量和维护成本较高 + +**示例:** +```ts +// 伪代码示例,实际命令式API以官方文档为准 +let button = createButton("Click Me"); +button.setOnClick(() => doSomething()); +addToLayout(button); +``` + +## 自定义能力概述 + +自定义能力为开发者提供了突破框架默认能力的手段,包括自定义节点、扩展、渲染等。 + +**能力边界:** +- 可自定义UI组件的渲染、布局、事件等 +- 可扩展属性、手势、绘制等能力 +- 适合有特殊UI、性能或渲染需求的场景 + +**典型场景:** +- 需要自定义绘制、特殊动画、复杂交互的业务需求 +- 性能优化、底层渲染定制 + +**示例:** +```ts +// 自定义节点示例 +@CustomNode +class MyNode extends FrameNode { + // 实现自定义布局、绘制、事件等 +} + +// 自定义扩展示例 +@AttributeModifier +class MyModifier { + // 实现自定义属性扩展 +} +``` + ## 两种开发范式 针对不同的应用场景及技术背景,方舟UI框架提供了两种开发范式,分别是[基于ArkTS的声明式开发范式](arkts-ui-development-overview.md)(简称“声明式开发范式”)和[兼容JS的类Web开发范式](ui-js-overview.md)(简称“类Web开发范式”)。 diff --git a/zh-cn/application-dev/ui/ui-debugging.md b/zh-cn/application-dev/ui/ui-debugging.md new file mode 100644 index 0000000000000000000000000000000000000000..71eb9f73d9346ce56a5afc4df75f6bdb2577df82 --- /dev/null +++ b/zh-cn/application-dev/ui/ui-debugging.md @@ -0,0 +1,556 @@ +# UI调试 + +## 概述 + +UI调试是OpenHarmony应用开发中的重要环节,通过系统化的调试工具和方法,开发者可以有效地分析UI性能、定位问题、优化用户体验。本章节详细介绍ArkUI框架的调试能力,包括DFX打点、关键流程trace、性能分析等核心功能。 + +## DFX打点系统 + +### HiTraceMeter性能打点 + +HiTraceMeter提供系统性能打点接口,用于跟踪UI渲染、布局、事件处理等关键流程的性能数据。 + +#### 基本概念 + +**HiTraceMeter Tag**:跟踪数据使用类别,称作HiTraceMeter Tag,一般每个软件子系统对应一个tag。应用中的HiTraceMeter打点的tag是HITRACE_TAG_APP。 + +#### 接口说明 + +| 接口名 | 描述 | +|--------|------| +| startSyncTrace(level: HiTraceOutputLevel, name: string, customArgs?: string): void | 开启一个同步时间片跟踪事件,分级控制跟踪输出。
**说明**:从API version 19开始,支持该接口。 | +| finishSyncTrace(level: HiTraceOutputLevel): void | 结束一个同步时间片跟踪事件,分级控制跟踪输出。level必须与流程开始的startSyncTrace对应参数值保持一致。
**说明**:从API version 19开始,支持该接口。 | +| startAsyncTrace(level: HiTraceOutputLevel, name: string, taskId: number, customCategory: string, customArgs?: string): void | 开启一个异步时间片跟踪事件,分级控制跟踪输出。taskId是trace中用来表示关联的ID,如果有多个name相同的任务并行执行,则开发者每次调用startAsyncTrace时传入的taskId需不同;如果具有相同name的任务是串行执行的,则taskId可以相同。
**说明**:从API version 19开始,支持该接口。 | +| finishAsyncTrace(level: HiTraceOutputLevel, name: string, taskId: number): void | 结束一个异步时间片跟踪事件,分级控制跟踪输出。level、name和taskId必须与流程开始的startAsyncTrace对应参数值保持一致。
**说明**:从API version 19开始,支持该接口。 | +| traceByValue(level: HiTraceOutputLevel, name: string, count: number): void | 整数跟踪事件,分级控制跟踪输出。name、count两个参数分别用来标记一个预跟踪的整数变量名及整数值。
**说明**:从API version 19开始,支持该接口。 | +| isTraceEnabled(): boolean | 判断当前是否开启应用trace捕获。应用trace捕获未开启时,HiTraceMeter性能跟踪打点无效。
**说明**:从API version 19开始,支持该接口。 | + +> **注意:** +> +> [用户态trace格式](./hitracemeter-view.md#用户态trace格式说明)使用竖线 `|` 作为分隔符,所以通过HiTraceMeter接口传递的字符串类型参数应避免包含该字符,防止trace解析异常。 + +HiTraceMeter打点接口按功能/行为分类,主要分三类:同步时间片跟踪接口、异步时间片跟踪接口和整数跟踪接口。无论同步时间片跟踪接口还是异步时间片跟踪接口,接口本身都是同步接口,不是异步接口。HiTraceMeter打点接口可与[HiTraceChain](./hitracechain-guidelines-arkts.md)一起使用,进行跨设备/跨进程/跨线程的打点关联与分析。 + +- 同步时间片跟踪接口用于顺序执行的打点场景。 +- 异步时间片跟踪接口用于在异步操作执行前进行开始打点,在异步操作完成后进行结束打点。异步跟踪的开始和结束由于不是顺序发生的,解析trace时需要通过name与taskId参数进行识别,name与taskId参数相同的异步跟踪开始与结束打点相匹配。 +- 整数跟踪接口用于跟踪整数变量。 + +**参数解析** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| level | enum | 是 | 跟踪输出级别,低于系统阈值的跟踪将不会被输出。
log版本阈值为INFO,nolog版本阈值为COMMERCIAL。 | +| name | string | 是 | 要跟踪的任务名称或整数变量名称。 | +| taskId | number | 是 | 用来表示关联的ID,如果有多个name相同的任务是并行执行的,则开发者每次调用startAsyncTrace时传入的taskId需不同。 | +| count | number | 是 | 整数变量的值。 | +| customCategory | string | 是 | 自定义聚类名称,用于聚合同一类异步跟踪打点。
若不需要聚类,可传入一个空字符串。 | +| customArgs | string | 否 | 自定义键值对,若有多组键值对,使用逗号进行分隔,例"key1=value1,key2=value2"。
若不需要该参数,可不传入该参数或传入一个空字符串。 | + +> **说明:** +> +> [用户态trace](./hitracemeter-view.md#用户态trace格式说明)总长度限制512字符,超过的部分将会被截断,因此建议name、customCategory和customArgs三个字段的总长度不超过420字符,避免输出的用户态trace被截断。 + +#### UI性能打点示例 + +```typescript +import { hiTraceMeter } from '@kit.PerformanceAnalysisKit'; + +@Entry +@Component +struct Index { + @State message: string = 'Hello World'; + + build() { + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) + .onClick(() => { + // UI渲染性能打点 + hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'UI_Render_Start'); + + // 业务逻辑 + this.message = (this.message == 'Hello HiTrace') ? 'Hello World' : 'Hello HiTrace'; + + // 结束UI渲染性能打点 + hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); + }) + } + .width('100%') + } + .height('100%') + } +} +``` + +### HiTraceChain链路跟踪 + +HiTraceChain支持跨线程、跨进程的UI操作链路分析,用于跟踪UI操作的完整调用链。 + +#### 接口说明 + +| 接口名 | 描述 | +|--------|------| +| startTrace(name: string, traceId: number): void | 开始一个链路跟踪事件。
**说明**:从API version 19开始,支持该接口。 | +| finishTrace(name: string, traceId: number): void | 结束一个链路跟踪事件。
**说明**:从API version 19开始,支持该接口。 | + +**参数解析** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| name | string | 是 | 链路跟踪事件的名称。 | +| traceId | number | 是 | 链路跟踪事件的ID,用于标识同一个链路跟踪事件。 | + +#### 使用示例 + +```typescript +import { hiTraceChain } from '@kit.PerformanceAnalysisKit'; + +// 开始链路跟踪 +hiTraceChain.startTrace('UI_Operation_Chain', 1001); + +// UI操作 +this.performUIOperation(); + +// 结束链路跟踪 +hiTraceChain.finishTrace('UI_Operation_Chain', 1001); +``` + +### HiAppEvent事件记录 + +HiAppEvent用于记录UI相关的应用事件,便于问题定位和分析。 + +#### 接口说明 + +| 接口名 | 描述 | +|--------|------| +| write(eventInfo: EventInfo): void | 写入应用事件。
**说明**:从API version 19开始,支持该接口。 | + +**EventInfo参数解析** + +| 参数名 | 类型 | 必填 | 说明 | +|--------|------|------|------| +| domain | string | 是 | 事件领域,用于标识事件所属的业务领域。 | +| name | string | 是 | 事件名称,用于标识具体的事件类型。 | +| eventType | EventType | 是 | 事件类型,包括BEHAVIOR(行为)、FAULT(故障)、SECURITY(安全)、STATISTIC(统计)等。 | +| parameters | Record | 否 | 事件参数,用于记录事件的详细信息。 | + +**EventType枚举值** + +| 枚举值 | 说明 | +|--------|------| +| BEHAVIOR | 行为事件,记录用户行为或应用行为。 | +| FAULT | 故障事件,记录应用故障或异常。 | +| SECURITY | 安全事件,记录安全相关事件。 | +| STATISTIC | 统计事件,记录统计数据。 | + +#### UI事件记录示例 + +```typescript +import { hiAppEvent } from '@kit.PerformanceAnalysisKit'; + +// 记录UI渲染事件 +hiAppEvent.write({ + domain: 'UI_RENDER', + name: 'component_rendered', + eventType: hiAppEvent.EventType.BEHAVIOR, + parameters: { + component_name: 'Text', + render_time: 16 + } +}); + +// 记录UI交互事件 +hiAppEvent.write({ + domain: 'UI_INTERACTION', + name: 'button_clicked', + eventType: hiAppEvent.EventType.BEHAVIOR, + parameters: { + button_id: 'submit_btn', + click_time: Date.now() + } +}); + +// 记录UI性能事件 +hiAppEvent.write({ + domain: 'UI_PERFORMANCE', + name: 'frame_drop', + eventType: hiAppEvent.EventType.FAULT, + parameters: { + fps: 25, + threshold: 30, + duration: 1000 + } +}); +``` + +## 关键流程Trace + +### UI渲染流程 + +UI渲染流程是从组件构建到屏幕显示的完整渲染链路,包括以下关键步骤: + +#### 1. 组件构建阶段 + +```typescript +// 组件构建性能打点 +hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Component_Build'); + +// 组件构建逻辑 +@Entry +@Component +struct MyComponent { + build() { + Column() { + Text('Hello World') + Button('Click Me') + } + } +} + +hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); +``` + +#### 2. 布局计算阶段 + +```typescript +// 布局计算性能打点 +hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Layout_Calculation'); + +// 布局计算过程 +Column() { + Text('Hello World') + .width('100%') + .height(50) + Button('Click Me') + .width('50%') + .height(40) +} + +hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); +``` + +#### 3. 绘制阶段 + +```typescript +// 绘制性能打点 +hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Drawing_Process'); + +// 绘制逻辑 +Canvas(this.context) + .width('100%') + .height('100%') + .onReady(() => { + this.context.fillStyle = '#000000'; + this.context.fillRect(0, 0, 100, 100); + }) + +hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); +``` + +### 事件处理流程 + +事件处理流程包括用户交互事件的捕获、分发、处理机制。 + +#### 事件捕获打点 + +```typescript +// 事件捕获性能打点 +hiTraceMeter.startAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Event_Capture', 2001, 'UI_Event'); + +Button('Click Me') + .onClick(() => { + // 事件处理逻辑 + this.handleClick(); + + // 结束事件捕获打点 + hiTraceMeter.finishAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Event_Capture', 2001); + }) +``` + +#### 事件分发打点 + +```typescript +// 事件分发性能打点 +hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Event_Dispatch'); + +// 事件分发逻辑 +this.dispatchEvent(event); + +hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); +``` + +### 状态管理流程 + +状态管理流程跟踪数据变化到UI更新的状态同步过程。 + +#### 状态变化打点 + +```typescript +// 状态变化性能打点 +hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'State_Change'); + +@State count: number = 0; + +Button('Increment') + .onClick(() => { + // 状态变化 + this.count++; + + // 记录状态变化 + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'count_value', this.count); + + hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); + }) +``` + +## 性能打点 + +### 帧率监控 + +实时监控UI渲染帧率,识别卡顿问题。 + +#### 帧率打点示例 + +```typescript +import { hiTraceMeter, hilog } from '@kit.PerformanceAnalysisKit'; + +class FrameRateMonitor { + private frameCount: number = 0; + private lastTime: number = 0; + private readonly TAG: string = 'FrameRate'; + + startMonitoring() { + this.lastTime = Date.now(); + this.frameCount = 0; + + // 开始帧率监控 + hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'FrameRate_Monitor'); + } + + onFrame() { + this.frameCount++; + const currentTime = Date.now(); + + if (currentTime - this.lastTime >= 1000) { // 每秒计算一次 + const fps = this.frameCount; + hilog.info(0x0000, this.TAG, 'Current FPS: %{public}d', fps); + + // 记录帧率数据 + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'fps_value', fps); + + // 帧率过低警告 + if (fps < 30) { + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.WARN, 'low_fps_warning', fps); + } + + this.frameCount = 0; + this.lastTime = currentTime; + } + } + + stopMonitoring() { + hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); + } +} +``` + +### 内存分析 + +分析UI组件内存使用情况,优化内存占用。 + +#### hidebug内存监控接口 + +| 接口名 | 描述 | +|--------|------| +| getNativeHeapSize(): number | 获取native heap内存的已分配内存大小。
**说明**:从API version 9开始,支持该接口。 | +| getNativeHeapFreeSize(): number | 获取native heap内存的空闲内存大小。
**说明**:从API version 9开始,支持该接口。 | +| getPss(): number | 获取应用进程PSS内存大小。
**说明**:从API version 9开始,支持该接口。 | +| getSharedDirty(): number | 获取进程的共享脏内存大小。
**说明**:从API version 9开始,支持该接口。 | +| getPrivateDirty(): number | 获取进程的私有脏内存大小。
**说明**:从API version 9开始,支持该接口。 | + +#### 内存使用打点 + +```typescript +import hidebug from '@ohos.hidebug'; +import appManager from '@ohos.app.ability.appManager'; + +// 内存使用监控 +class MemoryMonitor { + monitorMemoryUsage() { + // 开始内存监控 + hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Memory_Monitor'); + + // 获取内存使用情况 + const nativeHeapSize = hidebug.getNativeHeapSize(); + const nativeHeapFreeSize = hidebug.getNativeHeapFreeSize(); + const pss = hidebug.getPss(); + const sharedDirty = hidebug.getSharedDirty(); + const privateDirty = hidebug.getPrivateDirty(); + + // 记录内存数据 + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'native_heap_size', nativeHeapSize); + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'native_heap_free_size', nativeHeapFreeSize); + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'pss_memory', pss); + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'shared_dirty', sharedDirty); + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'private_dirty', privateDirty); + + // 内存使用过高警告 + if (pss > 100 * 1024 * 1024) { // 超过100MB + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.WARN, 'high_memory_warning', pss); + } + + // 使用appManager获取应用内存大小 + appManager.getAppMemorySize().then((size) => { + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'app_memory_size', size); + }).catch((error) => { + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.ERROR, 'get_memory_error', 1); + }); + + hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); + } +} +``` + +### CPU分析 + +监控UI线程CPU使用率,识别性能瓶颈。 + +#### hidebug CPU监控接口 + +| 接口名 | 描述 | +|--------|------| +| getCpuUsage(): number | 获取进程的CPU占用率。
**说明**:从API version 9开始,支持该接口。 | + +#### CPU使用率打点 + +```typescript +import hidebug from '@ohos.hidebug'; + +// CPU使用率监控 +class CPUMonitor { + monitorCPUUsage() { + // 开始CPU监控 + hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'CPU_Monitor'); + + // 获取CPU使用率 + const cpuUsage = hidebug.getCpuUsage(); + + // 记录CPU数据 + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.INFO, 'cpu_usage', cpuUsage); + + // CPU使用率过高警告 + if (cpuUsage > 80) { + hiTraceMeter.traceByValue(hiTraceMeter.HiTraceOutputLevel.WARN, 'high_cpu_warning', cpuUsage); + } + + hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); + } +} +``` + +### 渲染性能分析 + +分析绘制、合成、显示等渲染环节的性能。 + +#### 渲染性能打点 + +```typescript +// 渲染性能监控 +class RenderPerformanceMonitor { + monitorRenderPerformance() { + // 开始渲染性能监控 + hiTraceMeter.startSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Render_Performance'); + + // 绘制阶段 + hiTraceMeter.startAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Drawing_Phase', 3001, 'Render'); + this.performDrawing(); + hiTraceMeter.finishAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Drawing_Phase', 3001); + + // 合成阶段 + hiTraceMeter.startAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Compositing_Phase', 3002, 'Render'); + this.performCompositing(); + hiTraceMeter.finishAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Compositing_Phase', 3002); + + // 显示阶段 + hiTraceMeter.startAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Display_Phase', 3003, 'Render'); + this.performDisplay(); + hiTraceMeter.finishAsyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO, 'Display_Phase', 3003); + + hiTraceMeter.finishSyncTrace(hiTraceMeter.HiTraceOutputLevel.INFO); + } +} +``` + +## 调试工具使用 + +### 命令行工具 + +#### hitrace性能跟踪 + +```bash +# 开启应用trace捕获 +hdc shell hitrace --trace_begin app + +# 执行UI操作 + +# 抓取trace数据 +hdc shell hitrace --trace_dump | grep UI + +# 结束trace捕获 +hdc shell hitrace --trace_finish +``` + +#### hilog日志查看 + +```bash +# 查看UI相关日志 +hdc shell hilog | grep "UI_DEBUG" + +# 实时监控日志 +hdc shell hilog -L + +# 过滤特定级别日志 +hdc shell hilog | grep "ERROR" +``` + +### 性能分析工具 + +#### SmartPerf使用 + +```bash +# 启动性能分析 +hdc shell smartperf start + +# 查看性能数据 +hdc shell smartperf dump + +# 停止性能分析 +hdc shell smartperf stop +``` + +## 调试最佳实践 + +### 1. 分层调试策略 + +- **应用层**:关注业务逻辑和用户交互 +- **框架层**:分析UI框架的性能和稳定性 +- **系统层**:监控系统资源和底层性能 + +### 2. 性能优化流程 + +- **性能基线建立**:确定性能目标和基准数据 +- **性能数据采集**:使用工具收集性能数据 +- **问题识别分析**:识别性能瓶颈和问题点 +- **优化方案实施**:针对性地进行优化 +- **效果验证**:验证优化效果并持续改进 + +### 3. 调试技巧 + +- **合理使用日志**:避免过度日志影响性能 +- **分级调试**:根据问题严重程度选择合适的调试方法 +- **数据驱动**:基于数据进行分析,避免主观判断 +- **持续监控**:建立持续的性能监控机制 + +通过系统化的UI调试方法,开发者可以更好地理解UI框架的运行机制,快速定位和解决性能问题,提升应用的用户体验。 \ No newline at end of file diff --git a/zh-cn/application-dev/ui/ui-internationalization-configuration-changes.md b/zh-cn/application-dev/ui/ui-internationalization-configuration-changes.md new file mode 100644 index 0000000000000000000000000000000000000000..80797e5d3e887ed425f14dfcade8ea3c209b8df0 --- /dev/null +++ b/zh-cn/application-dev/ui/ui-internationalization-configuration-changes.md @@ -0,0 +1,83 @@ +# UI国际化配置变更 + +本节介绍当系统语言、地区等配置变更时,应用如何适配和处理,确保UI资源和界面能够动态响应。 + +## 1. 配置变更场景 + +常见的配置变更包括: +- 系统语言/地区切换(如从中文切换到英文) +- 主题模式切换(如深色/浅色) +- 屏幕方向变化(横屏/竖屏) +- 字体大小、分辨率等系统设置变更 + +这些变更可能影响UI资源的加载和显示,需要应用能够及时响应。 + +## 2. 资源热切换与界面刷新 + +ArkUI支持在配置变更时自动加载匹配的资源目录(如string.json),但部分场景下(如自定义绘制、Canvas等)需手动刷新界面。 + +- **普通UI组件**:系统自动根据当前配置加载对应资源。 +- **自定义绘制/Canvas**:需监听配置变更事件,手动刷新内容。 + +## 3. 监听配置变更的API用法 + +可通过`commonEventManager`监听系统配置变更事件(如语言切换): + +```ts +import { BusinessError, commonEventManager } from '@kit.BasicServicesKit'; + +aboutToAppear() { + let subscriber = null; + let subscribeInfo = { + events: ["usual.event.LOCALE_CHANGED"], + }; + commonEventManager.createSubscriber(subscribeInfo, (err, data) => { + if (err) { + console.error(`Failed to create subscriber. Code is ${err.code}, message is ${err.message}`); + return; + } + subscriber = data; + if (subscriber !== null) { + commonEventManager.subscribe(subscriber, (err, data) => { + if (err) { + console.error(`订阅语言变更事件失败. Code is ${err.code}, message is ${err.message}`); + return; + } + // 监听到语言切换后,刷新UI或重新加载资源 + this.refreshUI(); + }) + } + }) +} +``` + +示例代码: + +```ts +@Entry +@Component +struct Index { + @State greetings: string = ''; + + aboutToAppear() { + let context = this.getUIContext().getHostContext(); + let resMgr = context.resourceManager; + let resId = $r('app.string.greetings').id; + this.greetings = resMgr.getStringSync(resId); + // 监听语言变更 + let subscribeInfo = { events: ["usual.event.LOCALE_CHANGED"] }; + commonEventManager.createSubscriber(subscribeInfo, (err, subscriber) => { + if (!err && subscriber) { + commonEventManager.subscribe(subscriber, () => { + // 语言切换后,重新获取资源 + this.greetings = resMgr.getStringSync(resId); + }) + } + }) + } + + build() { + Text(this.greetings) + } +} +``` diff --git a/zh-cn/application-dev/ui/ui-internationalization-overview.md b/zh-cn/application-dev/ui/ui-internationalization-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..fde21ecbd14204fafdc9155e4ec8499141dda6eb --- /dev/null +++ b/zh-cn/application-dev/ui/ui-internationalization-overview.md @@ -0,0 +1,49 @@ +# UI国际化概述 + +随着应用出海和全球化趋势的加速,UI国际化(Internationalization, I18n)已成为现代应用开发的必备能力。UI国际化不仅仅是简单的多语言支持,更是让应用界面能够灵活适配不同国家、地区、文化和用户习惯的系统性工程。ArkUI框架为开发者提供了完善的UI国际化能力,帮助应用在全球范围内提升用户体验和市场竞争力。 + +UI国际化的目标是: +- 让同一套代码和界面能够适配多种语言、地区和文化环境,无需为每个市场单独开发。 +- 降低后续本地化(L10n)和维护成本,提升开发效率。 +- 保证界面在不同语言下的布局、交互、视觉一致性和可用性。 +- 支持多语言热切换、界面镜像(RTL/LTR)、资源自动匹配等高级特性。 + +ArkUI UI国际化能力主要适用于: +- 需要支持多语言、多地区发布的应用(如面向全球用户的App)。 +- 需要适配阿拉伯语、希伯来语等从右到左(RTL)语言的场景。 +- 需要根据用户系统设置动态切换语言、主题、字体等配置的场景。 +- 需要高效管理和维护多语言资源、图片、格式化文本等内容的项目。 + +核心能力包括: +- 多语言资源配置与访问:通过限定词目录和资源文件,系统自动加载最合适的界面文本、图片等资源。 +- 界面镜像适配:支持LTR/RTL自动镜像,满足不同文化阅读习惯。 +- 配置变更响应:支持系统语言、主题等配置变更时的资源热切换和界面刷新。 +- 丰富的API和事件监听机制,便于开发者灵活实现个性化国际化需求。 + +通过合理利用ArkUI的UI国际化能力,开发者可以大幅提升应用的全球化适配能力,减少重复开发和维护工作,让应用在不同市场都能提供一致且优质的用户体验。 + +## 使用镜像能力 + +为满足不同语言用户的阅读习惯,ArkUI支持界面镜像(RTL/LTR)能力。通过设置组件的direction属性和使用通用方向属性(如start/end),可以让界面在阿拉伯语、希伯来语等从右到左的语言环境下自动镜像显示。 + +- 支持系统自动镜像和手动适配,提升全球化体验。 +- 适用于布局、图标、交互等多种UI元素。 +- 详细内容见[使用镜像能力](arkts-mirroring-display.md)。 + +## UI国际化资源配置 + +UI国际化的基础是资源的多语言管理。ArkUI通过资源限定词目录和string.json等资源文件,实现界面文本、图片等内容的多语言适配。开发者可为不同语言、地区创建独立的资源目录,系统会根据当前设备配置自动加载最合适的资源。 + +- 资源目录结构清晰,支持多语言、多地区、多主题等多维度适配。 +- 通过`$r('app.string.xxx')`等方式便捷访问资源,避免硬编码。 +- 支持运行时动态获取和切换指定语言资源,满足个性化需求。 +- 详细内容见[UI国际化资源配置](ui-internationalization-resource-config.md)。 + +## UI国际化配置变更 + +应用在运行过程中,用户可能切换系统语言、主题、字体等配置。ArkUI支持对这些配置变更的自动和手动响应,确保界面资源和显示内容能够动态更新。 + +- 普通UI组件会自动根据新配置加载资源。 +- 对于自定义绘制、Canvas等场景,需监听配置变更事件并手动刷新界面。 +- 提供API监听如语言切换等系统事件,便于开发者实现资源热切换。 +- 详细内容见[UI国际化配置变更](ui-internationalization-configuration-changes.md)。 diff --git a/zh-cn/application-dev/ui/ui-internationalization-resource-config.md b/zh-cn/application-dev/ui/ui-internationalization-resource-config.md new file mode 100644 index 0000000000000000000000000000000000000000..0dbdd00e32f7ac22fbb1f5b78befc69521870282 --- /dev/null +++ b/zh-cn/application-dev/ui/ui-internationalization-resource-config.md @@ -0,0 +1,104 @@ +# UI国际化资源配置 + +本节介绍如何在ArkUI项目中配置和访问多语言资源,实现UI的中英文等多语言切换。 + +## 1. 资源目录结构与命名规范 + +ArkUI支持通过在`resources`目录下创建不同语言/地区的限定词目录,实现多语言资源管理。常见结构如下: + +``` +resources +|---zh_CN/element/string.json // 中文资源 +|---en_US/element/string.json // 英文资源 +|---base/element/string.json // 默认资源 +``` + +- 目录命名需遵循[限定词规则](../quick-start/resource-categories-and-access.md#限定词目录)。 +- 每种语言/地区一个独立目录,便于系统自动匹配。 + +## 2. 多语言string.json配置示例 + +**中文(zh_CN/element/string.json):** +```json +{ + "string": [ + { "name": "greetings", "value": "你好,世界" }, + { "name": "save", "value": "保存" }, + { "name": "clear", "value": "清空" } + ] +} +``` + +**英文(en_US/element/string.json):** +```json +{ + "string": [ + { "name": "greetings", "value": "Hello, world" }, + { "name": "save", "value": "Save" }, + { "name": "clear", "value": "Clear" } + ] +} +``` + +## 3. 资源访问方式 + +ArkUI提供便捷的资源访问方式: + +- **模板语法**: + ```ts + Text($r('app.string.greetings')) // 根据系统语言自动显示对应文本 + ``` +- **带参数的字符串**: + ```ts + // string.json: { "name": "message", "value": "Hello, %1$s!" } + Text($r('app.string.message', 'LiHua')) + ``` +- **通过ResourceManager API访问**: + ```ts + let context = this.getUIContext().getHostContext(); + let resMgr = context.resourceManager; + let resId = $r('app.string.greetings').id; + let str = resMgr.getStringSync(resId); // 获取当前语言资源 + ``` + +## 4. 动态切换/获取指定语言资源 + +如需在运行时获取指定语言的资源,可用如下方式: + +```ts +let overrideConfig = resMgr.getOverrideConfiguration(); +overrideConfig.locale = "en_US"; // 指定为英文 +let overrideResMgr = resMgr.getOverrideResourceManager(overrideConfig); +let enStr = overrideResMgr.getStringSync(resId); // 获取英文资源 +``` + +完整示例: +```ts +@Entry +@Component +struct Index { + @State englishString: string = ""; + @State chineseString: string = ""; + + getStrings() { + let context = this.getUIContext().getHostContext(); + let resMgr = context.resourceManager; + let resId = $r('app.string.greetings').id; + // 当前系统语言 + this.chineseString = resMgr.getStringSync(resId); + // 指定英文 + let overrideConfig = resMgr.getOverrideConfiguration(); + overrideConfig.locale = "en_US"; + let overrideResMgr = resMgr.getOverrideResourceManager(overrideConfig); + this.englishString = overrideResMgr.getStringSync(resId); + } + + build() { + Column() { + Button('获取多语言字符串').onClick(() => this.getStrings()) + Text(this.chineseString) + Text(this.englishString) + } + } +} +```