Appearance
渲染性能优化
鸿蒙渲染优化:120Hz 高刷、避免掉帧、LazyForEach、组件复用。
1. 渲染原理
1.1 渲染流水线
渲染流水线(每帧 16.67ms @ 60Hz)
├─ 输入事件处理 (2ms)
├─ 布局计算 (Layout) (3ms)
├─ 绘制命令生成 (3ms)
├─ GPU 渲染 (5ms)
├─ 合成与显示 (3.67ms)
└─ 总耗时 < 16.67ms(否则掉帧)1.2 掉帧原因
常见掉帧原因:
├─ 布局过于复杂(嵌套过深)
├─ 大量组件同时渲染
├─ 主线程执行耗时操作
├─ 频繁触发状态更新
├─ 图片加载/解码阻塞
└─ 动画过于复杂2. LazyForEach 懒加载
2.1 列表懒加载
typescript
// ❌ 错误:ForEach 渲染大量数据
@Entry
@Component
struct LongList {
@State items: Array<Item> = []
build() {
Scroll() {
Column() {
ForEach(this.items, (item: Item) => {
ListItem({ item: item })
})
}
}
}
}
// 问题:1000 条数据会创建 1000 个组件,内存爆炸
// ✅ 正确:LazyForEach 懒加载
@Entry
@Component
struct LongList {
@State items: Array<Item> = []
build() {
List() {
LazyForEach(this.items, (item: Item) => {
ListItem({ item: item })
}, (item: Item) => item.id) // 必须提供 key
}
}
}
// LazyForEach 只渲染可见区域 + 预加载区域2.2 LazyForEach 优化
typescript
@Entry
@Component
struct OptimizedList {
@State items: Array<Item> = []
build() {
List({
space: 10, // item 间距
initialIndex: 0 // 初始显示位置
}) {
LazyForEach(this.items, (item: Item) => {
ListItem() {
Row() {
Image(item.avatar)
.width(50)
.height(50)
Column() {
Text(item.title)
Text(item.subtitle)
}
}
.width('100%')
.padding(10)
}
}, (item: Item) => item.id)
}
.onReachEnd(() => {
// 滚动到底部加载更多
this.loadMore()
})
}
}3. 组件复用
3.1 避免重复创建
typescript
// ❌ 错误:每次 build 都创建新对象
@Entry
@Component
struct BadComponent {
@State count: number = 0
build() {
Column() {
// 每次都创建新数组,触发重新渲染
ForEach([1, 2, 3, 4, 5], (item: number) => {
Text(item.toString())
})
}
}
}
// ✅ 正确:缓存数据
@Entry
@Component
struct GoodComponent {
@State count: number = 0
private dataList: number[] = [1, 2, 3, 4, 5] // 缓存
build() {
Column() {
ForEach(this.dataList, (item: number) => {
Text(item.toString())
})
}
}
}3.2 条件渲染优化
typescript
// ❌ 错误:条件判断放在 build 内层
@Entry
@Component
struct BadCondition {
@State show: boolean = false
build() {
Column() {
ForEach(this.items, (item: Item) => {
if (this.show) { // 每次渲染都判断
Text(item.title)
}
})
}
}
}
// ✅ 正确:条件渲染
@Entry
@Component
struct GoodCondition {
@State show: boolean = false
build() {
Column() {
if (this.show) {
ForEach(this.items, (item: Item) => {
Text(item.title)
})
}
}
}
}4. 图片优化
4.1 图片加载
typescript
// ✅ 正确:指定宽高、使用缓存
Image($r('app.media.avatar'))
.width(100)
.height(100)
.objectFit(ImageFit.Cover)
.placeholder($r('app.media.placeholder')) // 占位图
.onComplete(() => {
console.log('图片加载完成')
})5. 面试高频考点
Q1: 列表性能优化?
回答:使用 LazyForEach 替代 ForEach,只渲染可见区域;提供唯一 key;避免在 build 中创建对象。
Q2: 掉帧如何排查?
回答:使用 DevEco Profiler 查看渲染耗时,检查布局嵌套、主线程耗时操作、图片加载。
🐱 小猫提示:渲染优化记住 "LazyForEach、组件复用、避免重复创建、图片指定宽高、120Hz 适配"。