Skip to content

启动优化

应用启动速度直接影响用户体验,鸿蒙提供多种启动优化手段。


1. 启动流程分析

┌─────────────────────────────────────────────┐
│           冷启动流程                         │
├─────────────────────────────────────────────┤
│ 1. 进程创建 (Process Start)                  │
│    - Zygote fork                            │
│    - 加载运行时                              │
├─────────────────────────────────────────────┤
│ 2. Application 初始化                        │
│    - onCreate()                             │
│    - 全局变量初始化                          │
├─────────────────────────────────────────────┤
│ 3. UIAbility 创建                           │
│    - onCreate()                             │
│    - 页面路由初始化                          │
├─────────────────────────────────────────────┤
│ 4. 首屏渲染                                 │
│    - build() 执行                           │
│    - ViewTree → RenderTree → LayerTree      │
│    - GPU 合成输出                            │
└─────────────────────────────────────────────┘

目标:冷启动 < 2 秒,热启动 < 500ms

2. Application 层优化

延迟初始化

typescript
// ❌ 不推荐:在 onCreate 中做大量初始化
class MyApplication extends AbilityStage {
  async onCreate() {
    // 阻塞主线程
    initSDK1();
    initSDK2();
    initSDK3();
    loadConfig();
    preloadData();
  }
}

// ✅ 推荐:按需延迟初始化
class MyApplication extends AbilityStage {
  async onCreate() {
    // 只初始化必要的
    await initCoreSDK();
    
    // 非必要的延迟到空闲时
    this.scheduleIdleTask(() => {
      initAnalytics();
      initPushSDK();
    });
  }
  
  private scheduleIdleTask(task: () => void): void {
    setTimeout(task, 1000);  // 1 秒后执行
  }
}

异步初始化

typescript
class MyApplication extends AbilityStage {
  async onCreate() {
    // 并行初始化多个 SDK
    await Promise.all([
      this.initSDK1(),
      this.initSDK2(),
      this.initSDK3()
    ]);
  }
  
  private async initSDK1(): Promise<void> {
    // 异步初始化
  }
  
  private async initSDK2(): Promise<void> {
    // 异步初始化
  }
  
  private async initSDK3(): Promise<void> {
    // 异步初始化
  }
}

3. UIAbility 层优化

简化 onCreate

typescript
// ❌ 不推荐
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
  // 耗时操作阻塞 onCreate
  let data = await loadDataFromDB();
  let config = await fetchRemoteConfig();
  this.globalData = { data, config };
}

// ✅ 推荐
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
  // 只做必要初始化
  this.router = new Router();
  
  // 数据加载放到页面级
}

懒加载数据

typescript
@Entry
@Component
struct HomePage {
  @State data: DataType | null = null;
  private isLoading: boolean = false;
  
  aboutToAppear() {
    // 异步加载,不阻塞 UI
    this.loadData();
  }
  
  async loadData(): Promise<void> {
    if (this.isLoading) return;
    this.isLoading = true;
    
    try {
      this.data = await fetchData();
    } finally {
      this.isLoading = false;
    }
  }
  
  build() {
    Column() {
      if (this.data === null) {
        LoadingProgress()  // 显示加载状态
      } else {
        ContentDisplay({ data: this.data })
      }
    }
  }
}

4. 首屏渲染优化

简化 build()

typescript
// ❌ 不推荐:复杂的 build 逻辑
build() {
  Column() {
    ForEach(this.items, (item) => {
      ComplexComponent({ data: item })
    })
    // 大量嵌套组件
  }
}

// ✅ 推荐:扁平化结构
build() {
  Column() {
    Header()
    ContentList()
    Footer()
  }
}

@Component
struct ContentList {
  build() {
    List() {
      LazyForEach(dataSource, renderItem)
    }
  }
}

骨架屏(Skeleton)

typescript
@Entry
@Component
struct SkeletonPage {
  @State isLoading: boolean = true;
  @State data: DataType | null = null;
  
  aboutToAppear() {
    this.loadData().then(() => {
      this.isLoading = false;
    });
  }
  
  build() {
    Column() {
      if (this.isLoading) {
        // 骨架屏
        SkeletonLayout()
          .width('100%')
          .height(200)
      } else {
        // 真实内容
        ContentDisplay({ data: this.data })
      }
    }
  }
}

@Component
struct SkeletonLayout {
  build() {
    Column() {
      Row().width('90%').height(20).backgroundColor(Color.LightGray).margin({ bottom: 10 })
      Row().width('80%').height(20).backgroundColor(Color.LightGray).margin({ bottom: 10 })
      Row().width('70%').height(20).backgroundColor(Color.LightGray)
    }
    .padding(16)
  }
}

5. 预加载策略

资源预加载

typescript
class ResourcePreloader {
  private static instance: ResourcePreloader;
  private imageCache: Map<string, PixelMap> = new Map();
  
  static getInstance(): ResourcePreloader {
    if (!ResourcePreloader.instance) {
      ResourcePreloader.instance = new ResourcePreloader();
    }
    return ResourcePreloader.instance;
  }
  
  async preloadImages(urls: string[]): Promise<void> {
    // 后台线程预加载
    for (let url of urls) {
      try {
        let image = await loadImage(url);
        this.imageCache.set(url, image);
      } catch {}
    }
  }
  
  getImage(url: string): PixelMap | undefined {
    return this.imageCache.get(url);
  }
}

// 在 Application 空闲时预加载
aboutToAppear() {
  ResourcePreloader.getInstance().preloadImages([
    'common/image1.png',
    'common/image2.png'
  ]);
}

6. 启动监控

启动时间埋点

typescript
class StartupMonitor {
  private static startTime: number = Date.now();
  private static milestones: Record<string, number> = {};
  
  static mark(milestone: string): void {
    this.milestones[milestone] = Date.now() - this.startTime;
    console.log(`[${milestone}] ${this.milestones[milestone]}ms`);
  }
  
  static report(): void {
    // 上报启动数据
    let metrics = {
      processStart: this.milestones['process'],
      applicationCreate: this.milestones['application'],
      abilityCreate: this.milestones['ability'],
      firstRender: this.milestones['firstFrame']
    };
    
    uploadMetrics(metrics);
  }
}

// 在各阶段打点
class MyApplication extends AbilityStage {
  onCreate() {
    StartupMonitor.mark('application');
  }
}

@Entry
@Component
struct MainPage {
  aboutToAppear() {
    StartupMonitor.mark('ability');
  }
  
  onPageShow() {
    StartupMonitor.mark('firstFrame');
    StartupMonitor.report();
  }
}

7. 面试高频问题

Q1: 如何优化冷启动速度?

  1. 减少 Application onCreate 中的工作
  2. 异步/并行初始化 SDK
  3. 延迟非必要初始化
  4. 简化首屏 build() 逻辑
  5. 使用骨架屏提升感知速度

Q2: 启动优化的核心指标?

:冷启动 < 2 秒,热启动 < 500ms。关键节点:进程创建、Application 初始化、UIAbility 创建、首帧渲染。

Q3: 如何监控启动性能?

:在关键节点打点(mark),记录各阶段耗时,上报分析。关注 P50/P90/P99 分位数。


8. 与 Android 对照

概念HarmonyOSAndroid
ApplicationAbilityStageApplication
ActivityUIAbilityActivity
启动监控自定义埋点Performance Monitor
骨架屏自定义组件Skeleton Layout
预加载手动实现ContentProvider + AppStartup

面试提示:启动优化是性能优化的首要考点,需掌握完整的启动流程和优化手段。