aboutToAppear 在 build 之前,同步任务直接加到首帧上

冷启动白屏最常见的误诊,是把它归因成“鸿蒙启动就是慢”。拆开看,相当一部分白屏来自应用自己塞进主线程的同步任务。有实测案例在 aboutToAppear 里跑了两亿次同步循环,UI 线程被彻底拖死,用户看到的就是长时间白屏。另一个典型是在 UIAbility.onCreate 里同步解几兆的数据库导出,首帧被硬生生推到两秒左右。

aboutToAppear 在 build() 之前执行。放在这里的同步 IO、大 JSON 解析、第三方 SDK 首次初始化,都会原封不动地加到首帧时间上。

首帧只需要“能画出第一屏”的数据

冷启动优化的核心不是让初始化变快,而是把首帧不需要的东西赶出关键路径。首屏渲染必需的最小缓存留下,网络请求、埋点预热、非首屏模块的数据库迁移全部后移。

typescript

@Entry
@Component
struct HomePage {
  @State ready: boolean = false;
  @State firstScreen: string[] = [];

  aboutToAppear(): void {
    // 只读首帧必需的最小缓存
    this.firstScreen = this.readCachedFirstScreen();
    this.ready = true;

    // 其余初始化推到首帧之后
    setTimeout(() => {
      this.prefetchNetworkData();
      this.warmUpAnalytics();
    }, 0);
  }

  build() {
    if (!this.ready) {
      SkeletonScreen()          // 骨架屏,不是白屏
    } else {
      ListContent({ data: this.firstScreen })
    }
  }
}

setTimeout(..., 0) 在这里不是“延时”,而是把任务从首帧关键路径上摘出去。骨架屏让用户感知到“正在出来”,而不是对着一片白猜应用是不是卡死了。

常见错误是把异步做成了假异步:setTimeout 里又同步调了一个阻塞方法,主线程该卡还是卡。真正的后移要么进 TaskPool,要么拆成多个小任务,让事件循环有机会渲染。还有一点:onCreate 里保留崩溃上报和路由决策所需的上下文就够了,网络库、数据库建表放到 onWindowStageCreate 之后异步执行。

参考基线:TTID(首帧完成时延)参考值 680ms,超过 1500ms 必须优化;TTFD 1100ms 是“启动缓慢”参考线。先拿 Profiler 把 Process Creating 到 First Frame 的每一段打出来,再决定移谁,比凭感觉拆任务可靠得多。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐