Appearance
启动优化
应用启动速度直接影响用户体验,鸿蒙提供多种启动优化手段。
1. 启动流程分析
┌─────────────────────────────────────────────┐
│ 冷启动流程 │
├─────────────────────────────────────────────┤
│ 1. 进程创建 (Process Start) │
│ - Zygote fork │
│ - 加载运行时 │
├─────────────────────────────────────────────┤
│ 2. Application 初始化 │
│ - onCreate() │
│ - 全局变量初始化 │
├─────────────────────────────────────────────┤
│ 3. UIAbility 创建 │
│ - onCreate() │
│ - 页面路由初始化 │
├─────────────────────────────────────────────┤
│ 4. 首屏渲染 │
│ - build() 执行 │
│ - ViewTree → RenderTree → LayerTree │
│ - GPU 合成输出 │
└─────────────────────────────────────────────┘
目标:冷启动 < 2 秒,热启动 < 500ms2. 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: 如何优化冷启动速度?
答:
- 减少 Application onCreate 中的工作
- 异步/并行初始化 SDK
- 延迟非必要初始化
- 简化首屏 build() 逻辑
- 使用骨架屏提升感知速度
Q2: 启动优化的核心指标?
答:冷启动 < 2 秒,热启动 < 500ms。关键节点:进程创建、Application 初始化、UIAbility 创建、首帧渲染。
Q3: 如何监控启动性能?
答:在关键节点打点(mark),记录各阶段耗时,上报分析。关注 P50/P90/P99 分位数。
8. 与 Android 对照
| 概念 | HarmonyOS | Android |
|---|---|---|
| Application | AbilityStage | Application |
| Activity | UIAbility | Activity |
| 启动监控 | 自定义埋点 | Performance Monitor |
| 骨架屏 | 自定义组件 | Skeleton Layout |
| 预加载 | 手动实现 | ContentProvider + AppStartup |
面试提示:启动优化是性能优化的首要考点,需掌握完整的启动流程和优化手段。