应用冷启动与加载绘制首页
应用冷启动即当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用。
应用冷启动过程大致可分成以下四个阶段:应用进程创建&初始化、Application&Ability初始化、Ability生命周期、加载绘制首页。
加载绘制首页不仅是应用冷启动的四个阶段之一,还是首帧绘制最重要的阶段。而它可以分为三个阶段:加载页面、测量和布局、渲染。本文从这三个阶段入手,分成下面三个场景进行案例优化。
减少加载页面时间
减少加载页面时间可以通过按需加载、减少自定义组件生命周期耗时两种方法来实现。
按需加载
按需加载可以避免一次性初始化和加载所有元素,从而使首帧绘制时加载页面阶段的创建列表元素时间大大减少,从而提升性能表现。
案例:每一个列表元素都被初始化和加载,为了突出效果,方便观察,设定数组中的元素有10000个,使其在加载页面阶段创建列表内元素耗时大大增加。
@Entry
@Component
struct AllLoad {
@State arr: String[] = Array.from(Array<string>(10000), (val,i) =>i.toString());
build() {
List() {
ForEach(this.arr, (item: string) => {
ListItem() {
Text(`item value: ${
item}`)
.fontSize(20)
.margin({
left: 10 })
}
}, (item: string) => item.toString())
}
}
}
优化:LazyForEach替换ForEach,避免一次性初始化和加载所有元素。
class BasicDataSource implements IDataSource {
private listeners: DataChangeListener[] = [];
private originDataArray: string[] = [];
public totalCount(): number {
return 0;
}
public getData(index: number): string {
return this.originDataArray[index]
}
// 注册数据改变的监听器
registerDataChangeListener(listener: DataChangeListener): void {
if (this.listeners.indexOf(listener) < 0) {
console.info('add listener')
this.listeners.push(listener)
}
}
// 注销数据改变的监听器
unregisterDataChangeListener(listener: DataChangeListener): void {
const pos = this.listeners.indexOf(listener);
if (pos >= 0) {
console.info('remove listener')
this.listeners.splice(pos, 1)
}
}
// 通知组件重新加载所有数据
notifyDataReload(): void {
this.listeners.forEach(listener => {
listener.onDataReloaded()
})
}
// 通知组件index的位置有数据添加
notifyDataAdd(index: number): void {
this.listeners.forEach(listener => {
listener.onDataAdd(index)
})
}
// 通知组件index的位置有数据有变化
notifyDataChange(index: number): void {
this.listeners.forEach(listener => {
listener.onDataChange(index)
})
}
// 通知组件删除index位置的数据并刷新LazyForEach的展示内容
notifyDataDelete(index: number): void {
this.listeners.forEach(listener => {
listener.onDataDelete(index)
})
}
// 通知组件数据有移动
notifyDataMove(from: number, to: number): void {
this.listeners.forEach(listener => {
listener.onDataMove(from, to)
})
}
}
class MyDataSource extends BasicDataSource {
private dataArray: string[] = Array.from(Array<string>(10000