文章目录
- 前言
- 冷启动发生了什么
- 坑一:在 aboutToAppear 里干重活
- 代码实现
- 核心代码
- 坑二:首屏 build 里嵌套太深 / 列表全量渲染
- 完整示例
- 坑三:滥用全局单例初始化
- 代码解析
- 启动优化清单
- 常见误区(小白必踩)
- 完整可运行示例:冷启动优化要点
- 实现拆解
- 写在最后
前言
用户点开 app 到看到首屏,超过 2 秒就会明显觉得"慢"。启动慢是用户流失的第一杀手,但优化它其实有章法。
HarmonyOS 的启动分"冷启动"(app 进程都没起来)和"热启动"(后台挂着)。这篇文章聚焦最影响体感的冷启动,讲清楚时间花在哪、怎么省。
冷启动发生了什么
从你点图标到首屏可交互,大致经历:
- 系统创建进程、加载引擎
- 创建 Ability、执行
onCreate - 加载页面、执行
aboutToAppear、跑build() - 首帧渲染完成,用户可操作
你能控制的重点是2~4:Ability 初始化和首屏build()的耗时。
坑一:在 aboutToAppear 里干重活
最常见的启动慢元凶:
代码实现
aboutToAppear(){this.loadAllConfig()// 同步读大文件this.initThirdSDK()// 同步初始化重 SDKthis.queryBigData()// 同步查大表}这三个同步操作全堆在首屏创建时,主线程被占满,首帧迟迟出不来。
优化:延迟非必要初始化 + 异步化。
核心代码
aboutToAppear(){// 只做首屏必须的this.loadEssentialConfig()// 非必须的丢到空闲或后台setTimeout(()=>this.initThirdSDK(),0)taskpool.execute(newtaskpool.Task(this.queryBigData))}- 首屏只加载必需配置。
- 第三方 SDK、大数据查询延后或进 TaskPool,不阻塞首帧。
坑二:首屏 build 里嵌套太深 / 列表全量渲染
首屏布局如果又深又重,测量+渲染就慢。
完整示例
// 优化:首屏只渲染可见内容,列表用 LazyForEachList(){LazyForEach(this.dataSource,(item)=>{ListItem(){FirstScreenItem({item})}},(item)=>item.id)}- 首屏列表用
LazyForEach,别一次性建几千项。 - 减少首屏组件层级,隐藏的 tab 内容等切换时再渲染。
坑三:滥用全局单例初始化
一些"工具类"在模块顶层就new了个重对象,app 一启动就被迫初始化。改成"懒加载":
代码解析
// 不好:模块加载即创建exportconstheavyUtil=newHeavyUtil()// 好:用到才创建let_util:HeavyUtil|null=nullexportfunctiongetUtil():HeavyUtil{if(!_util)_util=newHeavyUtil()return_util}启动优化清单
| 手段 | 效果 |
|---|---|
| 首屏只做必需初始化 | 首帧提前 |
| 非必需延后/异步 | 不阻塞启动 |
| 列表用 LazyForEach | 启动内存↓ |
| 全局单例改懒加载 | 启动更快 |
| 减少首屏布局层级 | 渲染更快 |
常见误区(小白必踩)
| 误区 | 说明 |
|---|---|
aboutToAppear干重活 | 同步读大文件、初始化重 SDK 全堆在首屏,首帧迟迟出不来。 |
| 首屏全量渲染列表 | 首屏列表用 LazyForEach,别一次性建几千项。 |
| 全局单例不懒加载 | 模块顶层new重对象,app 一启动就被迫初始化,改成用到才创建。 |
下面这段代码可以直接复制到 DevEco Studio 里运行。建议你边读边敲,改一改文末「动手改一改」里的参数,亲眼看看效果。
完整可运行示例:冷启动优化要点
展示「延迟初始化」减少启动阻塞。
实现拆解
// 启动期只做必要的事,重活往后挪@Entry@Componentstruct Splash{@Stateready:boolean=falseaboutToAppear(){// 仅初始化首屏必要数据this.ready=true// 非首屏重活放到 idle 或用户进入后再做setTimeout(()=>{this.loadHeavy()},0)}privateloadHeavy(){console.info('首屏后再加载重资源')}build(){Column(){if(this.ready){Text('欢迎使用').fontSize(24)}}.width('100%').height('100%').justifyContent(FlexAlign.Center)}}你会看到什么:应用秒开进入首屏,「重资源加载」被推迟到首屏渲染后才执行,启动体感更快。
动手改一改:
- 把
setTimeout换成requestIdleCallback风格(空闲时执行)。 - 用
prefetch预加载下个页面资源。 - 在
module.json5精简abilities启动依赖。
写在最后
冷启动优化就一句口诀:首屏只做必要的,其余都往后推或丢后台。重点盯aboutToAppear和首屏build()这两个耗时热点。
建议你用 DevEco 的 Profiler 抓一次启动,看看时间到底花在哪——数据比感觉靠谱,找到最慢的那一步,优化它,启动能快一大截。