鸿蒙中常见的性能优化

性能优化场景

1.应用冷启动优化

应用冷启动概述

应用启动可以分为冷启动和热启动,当应用启动时,后台没有该应用的进程,这时系统会重新创建应用的进程, 这种启动方式就叫做冷启动 ;而热启动是当应用程序已经在后台运行,用户再次打开应用程序时,应用程序仍然在内存中,可以直接从内存中加载并继续之前的状态,而不需要重新初始化和加载资源。

减少主线程非UI耗时操作

在应用启动流程中,主要聚焦在执行UI相关操作中,为了更快的显示首页内容,不建议在主线程中执行非UI相关的耗时操作,建议通过异步任务进行延迟处理或放到其他子线程中执行,

缩短加载绘制首页阶段耗时

首页加载绘制阶段主要包含加载首页内容、测量布局、刷新组件并绘制。同样注意页面生命周期的处理函数,不要进行耗时操作,同时,应优先创建首页需要显示的组件,使用if分支语句,隐藏不需要显示的组件,减少创建过程的耗时。耗时操作建议通过异步任务延迟处理或者放到其他线程执行,线程并发方案可以参考:TaskPool和Worker的对比实践

2.长列表加载性能优化

动态预加载

LazyForEach懒加载可以通过使用Prefetcher来预取和预渲染数据。在使用Prefetcher后,除屏幕内显示的ListItem组件外,还会预先将屏幕可视区外的部分列表项数据进行预渲染和预取。这样当列表向下滑动时,会先显示预渲染组件,屏幕可视区外会动态调整预取范围。

布局优化

可以对ListItem进行布局优化,把线性布局修改为相对布局,就可以将最大嵌套层级从5层降低到2层。

3.应用包大小优化

配置so压缩选型

当前DevEco Studio默认打包应用时不压缩so库文件,配置so压缩选项后,DevEco Studio会将so库文件以压缩形式打包到包中,从而减小应用包大小。

多包场景下使用HSP共享代码和资源

当前系统提供了两种共享包,HAR静态共享包和HSP动态共享包。最大的不同之处在于:HAR中的代码和资源跟随使用方编译,如果有多个使用方,它们的编译产物中会存在多份相同拷贝;而HSP中的代码和资源可以独立编译,在运行时进程中代码和资源也只会存在一份。

在多包场景下,如果应用的多个HAP或HSP包使用HAR包实现代码和资源的共享,那么打包后的每个HAP或HSP包中都会存在一份共享HAR包的拷贝,导致App包中存在冗余代码和资源。如下图示例,应用模块HAP1和HAP2/HSP1都引用了HAR2和HAR3,打包后,App包中HAR2和HAR3存在多份重复拷贝,体积较大。

推荐开发者使用HSP代替HAR实现代码和资源共享。

4.文件上传下载性能提升

断点续传

断点续传功能的实现,不管是应用端还是服务器端都需要用到合理的技术来互相协同。在实际开发中,开发者无需亲自实现断点续传功能,只需对SDK进行合理配置。

文件上传

对于大文件断点续传上传,本文采用request(上传下载)模块中的request.agent任务托管接口,可以自动实现暂停继续重试等操作,无需手动将文件分片和记录上传分片信息

TypeScript 复制代码
private config: request.agent.Config = {
  action: request.agent.Action.UPLOAD,
  headers: HEADER,
  url: '',
  mode: request.agent.Mode.BACKGROUND,
  method: 'POST',
  title: 'upload',
  network: request.agent.Network.ANY,
  data: [],
  token: 'UPLOAD_TOKEN'
}
...
// 转换uri
private async getFilesAndData(cacheDir: string, fileUris: Array<string>): Promise<Array<request.agent.FormItem>> {
...
}
// 创建文件上传后台任务
async createBackgroundTask(fileUris: Array<string>) {
  if (this.context === undefined) {
    return;
  }
  // 获取上传url
  this.config.url = await urlUtils.getUrl(this.context);
  this.config.data = await this.getFilesAndData(this.context.cacheDir, fileUris);
  this.config.mode = request.agent.Mode.BACKGROUND;
  try {
    this.backgroundTask = await request.agent.create(this.context, this.config);
    await this.backgroundTask.start();
    let state = AppStorage.get<number>('backTaskState');
    if (state === BackgroundTaskState.PAUSE) {
      await this.backgroundTask.pause();
    }
    logger.info(TAG, `createBackgroundTask success`);
  } catch (err) {
    logger.error(TAG, `task  err, err  = ${JSON.stringify(err)}`);
  }
}
相关推荐
小满zs1 分钟前
React第十二章(useSyncExternalStore)
前端·javascript·react.js
Mrs_Lupin4 分钟前
React核心思维模型(一)
前端·react.js·前端框架
你不讲 wood16 分钟前
预览 PDF 文档
开发语言·前端·javascript·pdf·html·node·文件预览
DC妙妙屋26 分钟前
10.24.2024刷华为OD C题型(四) -- 对象list按照多个属性排序
1024程序员节
我就说好玩36 分钟前
基于echarts、php、Mysql开发的数据可视化大屏
前端·后端·信息可视化·echarts
2301_7891695437 分钟前
ai说ajax
前端·javascript·ajax
bitenum1 小时前
qsort函数的学习与使用
c语言·开发语言·学习·算法·visualstudio·1024程序员节
小白讲前端1 小时前
炫酷的登录框!(附源码)
前端·javascript·css·html
二川bro1 小时前
CSS兼容处理
前端·css
XiaoYu20021 小时前
31.JS高级-包管理工具详解
前端·javascript·程序员