【ArkUI 练中学】第14课:应用性能优化实战

本节目标

· 理解 ArkUI 应用性能的核心指标与官方标准(冷启动 ≤3000ms、点击响应 ≤1000ms、动画帧率 ≥60 帧)

· 掌握冷启动链路分析方法,能够使用 HiTrace + DevEco Profiler 获取冷启动瀑布图并识别关键路径

· 掌握"延迟、并行、裁剪、预置"四步法裁剪冷启动关键路径

· 掌握 ArkUI 渲染优化的核心手段:细粒度状态管理、组件拆分、@Reusable 组件复用、LazyForEach 懒加载

· 理解布局重绘的本质,掌握扁平化布局设计原则,避免不必要的布局重算

· 掌握内存泄漏的常见成因与检测工具(DevEco Profiler Allocation、JSLeakWatcher、hidumper)

· 掌握应用包体积优化的完整方法:资源压缩、so 库压缩、HSP 共享、分包策略与资源收缩

· 了解 DevEco Profiler 各分析模板的适用场景,能够根据问题类型选择合适的工具

· 能够为应用建立"分析---优化---验证"的性能治理闭环

一、性能核心指标与官方标准

1.1 关键性能指标

在开始优化之前,需要明确 ArkUI 应用的性能基线标准。华为官方给出的交互时延标准如下:

· 点击操作完成时延:≤1000ms(1 秒)

· 页面启动冷启动时长:≤3000ms

· 动画帧率:稳定 60 帧,最低不低于 45 帧

此外,应用冷启动时延大于 1100ms 即可认为启动缓慢,超过 3 秒将显著影响体验。研究表明,超过 2 秒的启动延迟会导致大量用户流失。

1.2 性能问题的根源分析

HarmonyOS 应用的性能瓶颈通常集中在以下几个层面:

冷启动链路过长:EntryAbility 的 onCreate 阶段同步加载大量资源或执行耗时初始化,导致白屏时间拉长。

UI 渲染帧率下降:复杂布局嵌套、频繁触发全量重建、图片解码阻塞主线程,均会引起掉帧。

内存增长失控:闭包持有 Context、事件监听未注销、大对象缓存未设上限,最终触发 OOM 或频繁 GC。

核心优化理念:保持"分析---优化---验证"循环,用数据驱动优化决策,而非凭感觉猜测。

二、冷启动优化

2.1 冷启动链路拆解

在 Stage 模型下,一次冷启动从用户点击图标到首帧可交互,大致经过以下阶段:

进程创建:AMS 调度、应用进程 fork、运行时初始化(ArkTS 运行时、字节码加载)------系统侧行为,开发者干预空间有限。

AbilityStage 初始化:AbilityStage.onCreate() 执行,通常承载全局初始化。

UIAbility 生命周期:onCreate() → onWindowStageCreate(),窗口创建、loadContent 加载首页。

首页构建与渲染:ArkUI 组件树 build、measure/layout、首帧提交。

数据就绪与可交互:首屏数据返回、列表填充,达到 TTI(Time To Interactive)。

关键认知:只有位于"点击 → 首帧"这条串行链路上的耗时才是关键路径。一个在子线程里跑了 800ms 的初始化,如果不阻塞主线程和首帧,就不在关键路径上,砍掉它对启动时间毫无帮助。

2.2 用 HiTrace 获取可信瀑布图

"无图不优化"------没有瀑布图,就没有关键路径,优化自然无的放矢。

系统 trace 只能看到框架级事件,业务初始化必须自己插桩。使用 @kit.PerformanceAnalysisKit 中的 hiTraceMeter 打自定义 trace 点:

typescript 复制代码
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';

export class StartupTracer {
  private static seq = 0;

  static sync<T>(name: string, block: () => T): T {
    const id = StartupTracer.seq++;
    hiTraceMeter.startTrace(name, id);
    try {
      return block();
    } finally {
      hiTraceMeter.finishTrace(name, id);
    }
  }
}

将每个启动期任务包裹在 trace 中,然后通过 DevEco Studio 的 Profiler(Launch 模板)或命令行抓取 trace:

bash 复制代码
# 设备上抓 5 秒 trace,覆盖冷启动全过程
hdc shell hitrace -t 5 -b 20480 app ohos ability ace > startup.ftrace

抓取前先执行 hdc shell aa force-stop 杀掉进程保证是冷启动。将 trace 导入 Profiler 后,自定义 trace 点会和框架事件排在同一条时间线上,这就是瀑布图。

2.3 延迟非必要初始化

在 onCreate 中只做最轻量的路由注册,首帧加载完毕后再用 TaskPool 异步初始化非关键模块:

typescript 复制代码
// ❌ 不推荐:在 onCreate 中同步初始化所有模块
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  DatabaseManager.init();   // 耗时操作
  AnalyticsSDK.init();      // 耗时操作
  ConfigLoader.loadAll();   // 读大量配置
}

// ✅ 推荐:仅初始化首帧必需项,其余延迟到空闲时段
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  RouterManager.register();   // 只做最轻量的路由注册
}

onWindowStageCreate(windowStage: window.WindowStage): void {
  windowStage.loadContent('pages/Index', (err) => {
    if (!err) {
      // 首帧加载完毕后,用 TaskPool 异步初始化非关键模块
      taskpool.execute((): void => {
        DatabaseManager.init();
        AnalyticsSDK.init();
      });
    }
  });
}

2.4 启动屏与骨架屏

使用系统级 startWindowIcon 配置启动屏图片,避免白屏。首页数据未就绪时展示骨架屏而非空白占位:

typescript 复制代码
@Component
struct SkeletonItem {
  build() {
    Row() {
      Column()
        .width(48).height(48).borderRadius(24)
        .backgroundColor('#E0E0E0')
      Column({ space: 8 }) {
        Column().width('60%').height(14)
          .backgroundColor('#E0E0E0').borderRadius(4)
        Column().width('40%').height(12)
          .backgroundColor('#E8E8E8').borderRadius(4)
      }
      .alignItems(HorizontalAlign.Start)
      .layoutWeight(1)
    }
    .padding(16)
  }
}

三、ArkUI 渲染优化

3.1 精准更新:避免无效重建

ArkUI 的状态驱动机制中,@State 变量变化会触发依赖它的节点重建。状态粒度过粗时,一个字段的更新可能导致整棵子树重绘。

错误示例:状态变量绑定在页面级组件上,一点小变化触发整个页面重绘:

typescript 复制代码
@State count: number = 0;
build() {
  Column() {
    Text("总数: " + this.count)
    this.heavyUI()   // 大组件区域,也被迫重建
    Button("增加", () => this.count++)
  }
}

优化写法:将可变 UI 拆分成独立组件,隔离重绘范围:

typescript 复制代码
@State count: number = 0;
build() {
  Column() {
    Text("总数: " + this.count)
    HeavyRenderer()   // 独立组件,不受 count 影响
    Button("增加", () => this.count++)
  }
}

@Component
struct HeavyRenderer {
  build() {
    // 重型组件区域
    // 不受上级状态影响,不会因 count 变化而重建
  }
}

拆分组件后,HeavyRenderer 不会因为状态变化而重建,性能直接提升。

对于列表项,优先使用 @ObjectLink + @Observed 把刷新粒度从"整个列表"缩小到"单个属性级别",让每个列表项独立响应自己的数据变化。

3.2 计算逻辑移出 UI 构建

不要在 build() 或 UI 声明里写重逻辑,否则每一帧都在做计算。将计算结果缓存到计算属性或后台任务中:

typescript 复制代码
// ❌ 不推荐:每次重建 UI 都执行计算
Text(() => this.expensiveComputeData())

// ✅ 推荐:缓存计算结果
private get computedData() {
  return this.cacheData ?? (this.cacheData = this.expensiveComputeData())
}

3.3 扁平化布局

减少自定义组件的嵌套,改为 @Builder 自定义构建方法。使用扁平化布局组件(如 RelativeContainer、Grid)替代多层 Column/Row 嵌套。对固定尺寸组件设置具体宽高,限制布局影响范围。

3.4 组件复用 @Reusable

@Reusable 标记的组件从组件树上被移除时,组件和其对应的 JSView 对象都会被放入复用缓存中。当列表滑动到新的 ListItem 需要被显示时,框架从复用缓存中查找可复用的组件节点,找到后更新数据并添加到组件树中,从而节省了组件节点和 JSView 对象的创建时间。

@Reusable 结合 LazyForEach 懒加载一起使用,可以进一步解决列表滑动场景的瓶颈问题,提供滑动场景下高性能创建组件的方式来提升滑动帧率。

typescript 复制代码
@Reusable
@Component
struct MessageItem {
  @State message: Message = new Message()

  aboutToReuse(params: Record<string, Object>): void {
    this.message = params.message as Message
  }

  aboutToRecycle(): void {
    // 放入缓存池前清理资源
  }

  build() {
    Row() {
      Image(this.message.avatar).width(40).height(40).borderRadius(20)
      Column() {
        Text(this.message.name).fontSize(16).fontWeight(FontWeight.Bold)
        Text(this.message.content).fontSize(14).fontColor(Color.Gray)
      }
    }
    .padding(12)
  }
}

Note:HarmonyOS 提供了 Repeat 组件作为 LazyForEach 的升级替代。通过 .virtualScroll() 开启懒加载模式,Repeat 自身即具备组件复用能力,无需额外实现 IDataSource 接口,直接使用普通数组即可,API 更简洁,性能也更优。

3.5 布局重绘的本质

ArkUI 是声明式 UI,数据变 → 组件刷新 → UI 重绘。但不是数据变了所有组件都重绘,而是"依赖该数据的组件才会重绘"。设计原则是:让该刷新的地方刷新,不该刷新的地方别被牵连。

常见问题与优化方式:

列表滑动卡顿 → 使用 LazyForEach,惰性构建,减少节点压力。改 UI 就整页面刷新 → 把 @State 拆到尽可能小的组件,控制刷新范围。动画掉帧 → 避免动画期间数据更新触发重绘。条件渲染频繁闪动 → 使用 Visibility 而不是 if else,避免布局重建。

四、内存优化与泄漏排查

4.1 内存分析工具

DevEco Profiler 提供了基础的内存场景分析 Allocation,可以用来分析应用运行时的内存分配及使用情况,识别和定位内存泄漏、内存抖动以及内存溢出等问题。

Memory 泳道指标:

· PSS:进程独占内存和按比例分配共享库占用内存之和

· RSS:进程独占内存和相关共享库占用内存之和

· USS:进程独占内存

展开 Memory 泳道后,子泳道展示 ArkTS Heap、Native Heap、GL/Graph、FilePage、Stack、.hap、.so 等分类的内存信息,可以按类型定位问题。

4.2 内存泄漏的常见成因

ArkTS 对象内存泄漏通常是因为对象在生命周期结束后仍未被解除引用,导致垃圾回收器无法识别并将其回收。常见原因包括:

Native 层强引用:在 Node-API 中对 ArkTS 对象创建了持久化强引用。

闭包捕获:内部函数持有对外部作用域 ArkTS 对象的引用,即使外部作用域已退出。

全局或模块级缓存:使用 Map、Array 缓存长期持有 ArkTS 对象。

4.3 JSLeakWatcher 内存泄漏检测

HarmonyOS 提供了 ArkTS 内存泄漏检测能力 JSLeakWatcher,可实现对具有生命周期的 ArkTS 组件对象定期执行泄漏自检测。当检测到泄漏时,会生成泄漏信息文件(*.rawheap 和 *.jsleaklist),导入 IDE 后可获取泄漏对象列表并直接跳转到引用链。

typescript 复制代码
// 应用在启动后调用 enableLeakWatcher() 接口开启检测
// 检测流程:
// 1. 通过 FinalizationRegistry 机制注册监控组件对象的 GC 回调
// 2. 组件被销毁时记录在 list1 中
// 3. 周期性执行 GC(默认 90 秒),成功回收的对象记录在 list2 中
// 4. list1 - list2 即为泄漏对象

4.4 内存优化最佳实践

及时释放资源:页面销毁时在 aboutToDisappear 中取消事件监听、销毁定时器、释放文件句柄。

缓存设置上限:LRU 缓存策略,大对象缓存设置最大容量,避免无限增长。

避免闭包持有 Context:使用 WeakReference 持有 Context,避免长生命周期对象引用短生命周期对象。

图片资源管理:远程图片提前缓存,使用 ImageCache;避免列表中大量同步图片;图片尺寸压缩,减少内存占用,防止 OOM。

五、包体积优化

5.1 包体积的影响

应用包体积直接影响三个关键指标:包体每增加 6MB,下载转化率下降约 1%;大包更新用户更容易放弃;部分应用市场将包体积作为推荐权重因素。

5.2 HAP 包结构与体积分析

bash 复制代码
# 解压 HAP 查看结构
unzip entry.hap -d hap_extracted
# 查看各目录大小
du -sh hap_extracted/*
# 详细分析(递归显示前 20 大文件)
du -ah hap_extracted | sort -rh | head -20

常见占比:resources/base/media 占 40%-60%(图片、动画),ets 占 20%-30%(代码),libs 占 10%-20%(原生库),rawfile 占 0%-10%(不压缩资源)。

5.3 资源优化

图片压缩与格式选择:WebP 比 PNG 压缩率高 30%-50%,支持透明通道;SVG 适合图标和简单图形,体积极小。批量转换 WebP:

bash 复制代码
for img in resources/base/media/*.png; do
  cwebp -q 85 "$img" -o "${img%.png}.webp"
done

启用资源收缩:在 build-profile.json5 中配置 "shrinkResources": true,移除未引用资源。

5.4 so 库压缩

DevEco Studio 默认在打包应用时不压缩 so 库文件。配置 so 压缩选项后,将 so 库文件压缩并打包到应用中,可以显著减小包体积。以 arm 默认库文件为例,压缩率可达 34%:

json5 复制代码
// module.json5
{
  "module": {
    "compressNativeLibs": true   // true 表示压缩 so 库
  }
}

5.5 使用 HSP 共享代码和资源

在应用存在多包(HAP、HSP)的场景中,使用 HSP 动态共享包在多个包之间共享代码和资源,消除使用 HAR 静态共享包导致的代码和资源重复拷贝,从而减小应用包大小。同时需要综合评估对编译性能的影响------大量使用 HSP 替代 HAR,会在编译引用这些 HSP 共享包的模块时触发更多的语言编译任务,导致编译耗时和编译内存占用增加。

5.6 依赖冲突解决与分包策略

使用 ohpm 的 override 机制或开启 resolve_conflict 解决依赖冲突,减少依赖包导致的重复编译问题。将不常用的功能作为按需加载的模块(Feature 分包),进一步精简首包体积。

5.7 代码混淆与压缩

json5 复制代码
// build-profile.json5
{
  "buildOption": {
    "arkOptions": {
      "runtimeOnly": false
    }
  },
  "targets": [
    {
      "name": "default",
      "buildOption": {
        "enableObfuscation": true,
        "enableMinification": true
      }
    }
  ]
}

六、DevEco Profiler 性能分析实战

6.1 各分析模板适用场景

DevEco Profiler 支持以下场景化分析任务模板:

Launch:分析应用启动耗时,分析启动周期各阶段的耗时情况,识别启动瓶颈。

ArkUI:定位由于组件耗时、页面布局、状态变量更新导致的卡顿问题。

Frame:深度分析应用卡顿丢帧原因。

Concurrency:显示并行并发应用的实际运行情况,帮助优化并行并发代码。

ArkWeb:定位 Web 应用加载和丢帧问题。

Network:定位 HTTP 协议栈网络信息诊断,进行网络请求分段耗时分析。

Time:改进函数执行效率的分析,深度录制函数调用栈及每帧耗时。

Allocation:分析应用内存资源占用情况,直观呈现不同分类的内存趋势。

Snapshot:支持多次拍摄 ArkTS 堆内存快照,分析差异,定位 ArkTS 内存问题。

CPU:深度采集 CPU 内核相关数据,呈现 CPU 使用率、时间片调度、频率等信息。

6.2 静态检测与动态检测

官方将性能工具分为静态检测(提前避坑)和动态检测(运行时抓虫)两大类。Code Linter 在写代码时实时揪出潜在性能问题,AppAnalyzer 给应用做"全身体检",一键生成性能诊断报告。

七、多元化习题

习题 1(判断题)

题目:在 HarmonyOS 冷启动优化中,只要砍掉 onCreate 中耗时最长的初始化方法,就一定能显著降低启动时间。

答案:错误

解读:只有位于"点击 → 首帧"这条串行链路上的耗时才是关键路径。一个在子线程里跑了 800ms 的初始化,如果不阻塞主线程和首帧,就不在关键路径上,砍掉它对启动时间毫无帮助。优化前必须先获取瀑布图,识别出真正的关键路径,做到"无图不优化"。

习题 2(单选题)

题目:以下哪种方式最适合在 ArkUI 中实现列表项的重绘隔离?

A. 将 @State 变量定义在页面根组件上

B. 使用 @ObjectLink + @Observed 将刷新粒度缩小到单个属性级别

C. 使用 ForEach 替代 LazyForEach

D. 将所有计算逻辑放在 build() 方法中执行

答案:B

解读:@State 变量变化会触发依赖它的节点重建,状态粒度过粗时一个字段的更新可能导致整棵子树重绘。使用 @ObjectLink + @Observed 可以把刷新粒度从"整个列表"缩小到"单个属性级别",让每个列表项独立响应自己的数据变化。选项 A 会导致重绘范围过大,选项 C 会加剧性能问题,选项 D 会导致每帧都在做计算。

习题 3(多选题)

题目:关于 ArkUI 渲染优化,以下说法正确的有(多选):

A. 将状态变量绑定在页面级组件上可以实现最小范围的重绘

B. 使用 @Reusable 组件复用可以减少列表滚动时组件创建和销毁的开销

C. 使用 Visibility 替代 if else 可以避免布局重建

D. 在 build() 方法中执行重计算逻辑可以提升渲染效率

答案:B、C

解读:@Reusable 标记的组件从组件树上被移除时会被放入复用缓存中,下次需要时优先从缓存池中取用,减少组件创建和销毁的开销,选项 B 正确。使用 Visibility 替代 if else 可以避免布局重建导致的条件渲染频繁闪动,选项 C 正确。将状态变量绑定在页面级组件上会导致重绘范围过大,选项 A 错误。在 build() 中写重逻辑会导致每一帧都在做计算,选项 D 错误。

习题 4(代码填空题)

题目:请补全以下代码,实现将非关键初始化模块延迟到首帧加载完毕后异步执行。

typescript 复制代码
onWindowStageCreate(windowStage: window.WindowStage): void {
  windowStage.loadContent('pages/Index', (err) => {
    if (!err) {
      // 在此处填写代码,异步初始化非关键模块
      ______________
    }
  });
}

答案:taskpool.execute((): void => { DatabaseManager.init(); AnalyticsSDK.init(); });

解读:在 onCreate 中只做最轻量的路由注册,首帧加载完毕后再用 TaskPool 异步初始化非关键模块。将非关键初始化放到子线程中执行,不阻塞主线程和首帧渲染,从而缩短冷启动时间。

习题 5(代码改错题)

题目:以下代码存在内存泄漏风险,请指出问题并修正。

typescript 复制代码
@Entry
@Component
struct MyPage {
  private timerId: number = -1;

  aboutToAppear(): void {
    this.timerId = setInterval(() => {
      console.log('tick');
    }, 1000);
  }

  build() {
    Column() {
      Text('Hello')
    }
  }
}

答案:代码中没有在页面销毁时清除定时器,导致 setInterval 持续执行并持有页面组件引用,造成内存泄漏。修正如下:

typescript 复制代码
@Entry
@Component
struct MyPage {
  private timerId: number = -1;

  aboutToAppear(): void {
    this.timerId = setInterval(() => {
      console.log('tick');
    }, 1000);
  }

  aboutToDisappear(): void {
    if (this.timerId !== -1) {
      clearInterval(this.timerId);
      this.timerId = -1;
    }
  }

  build() {
    Column() {
      Text('Hello')
    }
  }
}

解读:aboutToDisappear 在自定义组件析构销毁之前执行,是释放资源的正确时机。定时器、事件监听、文件句柄等资源都应在此回调中清理。

习题 6(简答题)

题目:简述 HarmonyOS 冷启动的完整链路阶段,以及如何使用 HiTrace 获取冷启动瀑布图来定位性能瓶颈。

答案:HarmonyOS 冷启动大致经过五个阶段:进程创建(AMS 调度、应用进程 fork、运行时初始化);AbilityStage 初始化(AbilityStage.onCreate() 执行);UIAbility 生命周期(onCreate() → onWindowStageCreate());首页构建与渲染(ArkUI 组件树 build、measure/layout、首帧提交);数据就绪与可交互(TTI)。

获取冷启动瀑布图的方法:首先在业务初始化代码中使用 hiTraceMeter.startTrace 和 hiTraceMeter.finishTrace 打自定义 trace 点;然后用 hdc shell hitrace 命令抓取 trace,或使用 DevEco Studio 的 Profiler Launch 模板录制;抓取前先执行 hdc shell aa force-stop 杀掉进程保证冷启动;将 trace 导入 Profiler 后,自定义 trace 点会和框架事件排在同一条时间线上形成瀑布图;通过分析瀑布图找出大块串行段和关键路径上的耗时操作。

解读:冷启动优化的核心是"无图不优化"。只有拿到瀑布图,才能区分串行阻塞的部分和并行无害的部分,从而精准裁剪关键路径。

习题 7(简答题)

题目:简述应用包体积优化的主要方法,以及 HSP 在包体积优化中的作用。

答案:包体积优化的主要方法包括:使用扫描工具分析 App 大小问题,识别重复文件和较大文件;图片格式转换(WebP/SVG)和压缩;配置 so 库压缩选项,将 so 库压缩后打包;启用资源收缩,移除未引用资源;使用代码混淆和压缩;将不常用功能作为按需加载的模块。

HSP 在包体积优化中的作用:在应用存在多包(HAP、HSP)的场景中,使用 HSP 动态共享包在多个包之间共享代码和资源,消除使用 HAR 静态共享包导致的代码和资源重复拷贝,从而减小应用包大小。

解读:HSP 的核心价值在于解决 HAR 静态共享包在多包场景下的代码和资源重复拷贝问题。HAR 在每个引用它的 HAP 中都会生成独立副本,而 HSP 在运行时复用,进程内只存一份。需要注意的是,大量使用 HSP 替代 HAR 会增加编译耗时和编译内存占用,需要综合评估。

八、本节知识点总结

性能核心指标

点击操作完成时延 ≤1000ms,冷启动时长 ≤3000ms,动画帧率稳定 60 帧、最低不低于 45 帧。冷启动时延大于 1100ms 即认为缓慢。

冷启动优化

冷启动链路分为进程创建、AbilityStage 初始化、UIAbility 生命周期、首页构建与渲染、数据就绪五个阶段。只有位于"点击 → 首帧"串行链路上的耗时才是关键路径。使用 HiTrace + DevEco Profiler 获取瀑布图,通过"延迟、并行、裁剪、预置"四步法优化。在 onCreate 中只做最轻量初始化,其余用 TaskPool 延迟异步执行。

渲染优化

将 @State 拆到尽可能小的组件,使用 @ObjectLink + @Observed 缩小刷新粒度。计算逻辑移出 build()。减少组件嵌套,使用扁平化布局。@Reusable 组件复用 + LazyForEach 懒加载是长列表性能优化的核心组合。使用 Visibility 替代 if else 避免布局重建。

内存优化

DevEco Profiler 的 Allocation 模板可分析 PSS/RSS/USS 内存指标,识别泄漏、抖动和溢出。JSLeakWatcher 可检测 ArkTS 组件对象泄漏。常见泄漏原因包括 Native 强引用、闭包捕获、全局缓存未设上限。在 aboutToDisappear 中释放定时器、事件监听等资源。

包体积优化

使用扫描工具分析包结构,图片转 WebP 压缩,配置 compressNativeLibs 压缩 so 库,配置 shrinkResources 移除未引用资源,使用 HSP 替代 HAR 消除重复拷贝,启用代码混淆和压缩,将不常用功能作为按需加载模块。

性能分析工具

DevEco Profiler 支持 Launch(启动耗时)、ArkUI(组件卡顿)、Frame(丢帧分析)、Allocation(内存分析)、Snapshot(堆快照)等模板。Code Linter 用于静态检测,AppAnalyzer 用于动态检测。核心工作流是"分析---优化---验证"。

本课总结

至此,ArkUI 练中学系列课程已完整覆盖从环境搭建、基础语法、组件复用、布局列表、路由导航、状态管理、动画手势、网络交互、数据持久化、模块化架构、测试调试、发布上架到性能优化的全链路知识体系。性能优化不是一次性的工作,而是贯穿开发全流程的持续实践。建议在实际项目中始终遵循"先测量、再优化、后验证"的原则,用数据驱动性能治理决策。

下节第15课:UI界面程序设计,UI框架还是用来写界面的,这是ArkUI框架在鸿蒙应用开发中的用武之地,核心所在。

相关推荐
用户593096009781 小时前
Flutter 鸿蒙化实战:flutter_tts 适配 OpenHarmony,文本转语音
harmonyos
PNP Robotics2 小时前
【PNP具身解读】GPT6 Astra:具身智能新范式,大模型 + Franka机器人快速落地验证一、GPT6 Astra 背后的布局、数据与具身方向
人工智能·学习·机器学习·机器人
小李不想当小白2 小时前
PCB结构与组成(PCB设计入门学习笔记)
经验分享·笔记·单片机·嵌入式硬件·学习·pcb工艺·pcb
那年窗外下的雪.2 小时前
第 02 天:Linux 权限、inode、目录项与链接
学习·http
XGStudio20243 小时前
免费安全的 - 二维码转换工具
学习·ai
邵奈一3 小时前
【紧急处理ZCode事件】ZCode 工作区快照静默上传:检测方法与三层防护实践
人工智能·学习·大模型·国产
那年窗外下的雪.3 小时前
AIDC 学习日志|第 27 天|EVPN 多归属收敛时间线与 Leaf2 接管验证
网络协议·学习·http·tcpdump
秦哈哈3 小时前
【HelloAgents】学习笔记(四)
学习·ai·agent
威哥爱编程4 小时前
HarmonyOS 互动卡片实战:摇一摇触发静态转动态,前景元素出框
华为·harmonyos·arkts