HarmonyOS鸿蒙Next中项目丢帧严重怎么优化呢?
HarmonyOS鸿蒙Next中项目丢帧严重怎么优化呢? 项目有个页面丢帧,无法通过性能检测,怎么进行优化。
用 Profiler 进行检测,确定哪方面引起的,然后针对进行优化。
减少节点优化
- RelativeContainer 通过相对布局实现扁平化。
- 绝对定位 通过锚点定位实现扁平化。
- Grid 通过二维布局实现扁平化。
自定义组件属性层级优化
其实减少层级一般开发过的都知道,但鸿蒙这里特殊的一个点就是第二条,当你用了自定义组件,属性就不要顺手写在用它的地方,这样会让节点层数多一层,包括你在List里或者Scroll里面写的各个组件占据的宽高也不行。copy个官方文档的图,看着更明显。 
减少布局计算优化
这个要讲一下鸿蒙的绘制流程,固定经过Build、Measure、Layout、Render流程。 当你第一次创建的时候,肯定就是全部都遍历走一遍。所以想性能好就是减少整体节点数。 但当你后续的更新,就需要考虑怎么减少布局计算了。很简单,鸿蒙是从组件树被影响的节点范围来考虑都哪些需要走这个流程进行更新的。你只需要给容易频繁更新的地方,设定好固定宽高,别让他的更新,影响到不需要更新的节点就可以了。因为写了固定宽高的组件布局边界就在这个宽高范围,他不动,周边的就不会有影响也跟着去重新计算绘制一遍 。
结论就是:频繁更新的布局,父组件能给固定宽高就尽量给,不要空着。其他不怎么更新的就只需要考虑尽量减少层级就可以了。
合理控制元素显示与隐藏
- 在对性能要求较高,并且会频繁切换元素的显示与隐藏的情况下,应该避免使用if条件判断,而改为通过visibility的属性控制,这样在切换Visibility.None和Visibility.Visible时,可以省去组件创建的时间,直接进入渲染过程。
- 如果组件的创建非常消耗资源,且不会立即使用,也并非频繁切换交互的情况下,只在特定条件下才会出现时,可以通过if/else来进行内容的显示与隐藏控制,来达到懒加载的效果。
最后再说两个文档没说,但是这次发现的UI规则
状态管理同一个页面尽量不要超过 30个,页面组件最好不要超过 50个。
我优化我们项目的这个播放页功能就是发现了,他页面内状态变量明显远超 30个(当然这肯定不是我写的),然后再加上需要绘制的东西也多,导致组件也超了。弄的丢帧超夸张。
怎么解决这个问题:
1、用class对象来承载一部分属性,通过一个状态管理器来统一处理。 2、用Modifier来承载一些属性。也是一个状态管理器统一处理。 对象的不举例子了,大家肯定都会,来个Modifier这个不常用的例子。
// 父组件:只传1个modifier对象,仅1个状态变量
struct CustomComponentModifier {
modifier: ColumnModifier = new ColumnModifier(); // 仅1个状态变量
aboutToAppear() {
this.modifier.width = 100; //赋值,或者根据逻辑更改状态变量值
this.modifier.height = 100;
this.modifier.backgroundColor = Color.Red;
}
build() {
ModifierCustom({ modifier: this.modifier }) // 仅传1个参数
}
}
// 子组件:仅接收1个modifier,无需多个@Prop
struct ModifierCustom {
@Require @Prop modifier: AttributeModifier<ColumnAttribute>; // 仅1个@Prop
build() {
Column() { Text('Hello World') }
.attributeModifier(this.modifier) // 内部设置属性,无__Common__节点
}
}
// 一次性应用所有属性,贴近组件原生接口
class ColumnModifier implements AttributeModifier<ColumnAttribute> {
applyNormalAttribute(instance: ColumnAttribute): void {
// 直接操作Column的属性实例,无中间状态传递
instance.width(this.width);
instance.height(this.height);
instance.backgroundColor(this.backgroundColor);
}
}
那是不是奇怪实际子组件多数都是分散的,更改几个控件的几个属性,而不是一个控件的多个属性,怎么办 有办法的。
假如我要给多个控件某几个常见属性设置不同的值。
// 自定义Modifier:包含所有分散控件的属性
class CustomCompModifier implements AttributeModifier<any> {
// Text控件属性
textValue: string = '';
textColor: ResourceColor = Color.Black;
// Button控件属性
btnBgColor: ResourceColor = Color.Red;
btnRadius: number = 0;
// Column控件属性
colWidth: number = 0;
colPadding: number = 0;
// 不需要实现applyNormalAttribute(因为不是给单个控件设属性,而是给自定义组件传属性包)
applyNormalAttribute(instance: any): void {}
}
子组件仅接收 1 个 Modifier 对象,内部给分散控件赋值:
@Component
struct MyCustomComp {
@Require @Prop modifier: CustomCompModifier; // 仅1个@Prop,监听1个对象
build() {
Column()
.width(this.modifier.colWidth)
.padding(this.modifier.colPadding) {
// Text控件用Modifier里的属性
Text(this.modifier.textValue).color(this.modifier.textColor)
// Button控件用Modifier里的属性
Button('操作')
.backgroundColor(this.modifier.btnBgColor)
.borderRadius(this.modifier.btnRadius)
}
}
}
父组件仅传 1 个 Modifier 对象,修改分散属性
@Entry
@Component
struct ParentComp {
// 仅1个Modifier对象,管理所有分散属性
compModifier: CustomCompModifier = new CustomCompModifier();
aboutToAppear() {
// 给分散控件的属性赋值(打包修改)
this.compModifier.textValue = 'Hello';
this.compModifier.textColor = Color.Black;
this.compModifier.btnBgColor = Color.Red;
this.compModifier.btnRadius = 8;
this.compModifier.colWidth = 200;
this.compModifier.colPadding = 10;
}
build() {
Column() {
MyCustomComp({ modifier: this.compModifier }) // 仅传1个参数
}
}
}
这样就完成了减少状态管理器的目的。如果还想优化还有空间的,比如你子组件有的是经常更新的有的是很少更新的对吧。那就拆开,不用一个Modifier,每次单独更新频率高的那个就可以了,性能更好一些。
另外 再再推荐一下用position 属性,真的能减少一些层级的。
更多关于HarmonyOS鸿蒙Next中项目丢帧严重怎么优化呢?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next项目丢帧优化方案:
- 布局优化:减少嵌套层级,使用
Column、Row替代多层Stack,避免过度绘制。 - 组件复用:对长列表使用
LazyForEach或RecyclerView,按需加载条目。 - 异步处理:耗时操作(如数据解析、图片解码)移至异步线程,主线程仅处理UI更新。
- 资源压缩:图片使用WebP格式,控制分辨率,避免大图直接渲染。
- 动画精简:减少复杂动画叠加,使用
animateTo替代频繁属性变更。 - 内存管理:及时释放未使用的资源,避免内存泄漏导致GC卡顿。
- 工具检测:通过DevEco Studio的Profiler监控帧率,定位耗时函数。
针对HarmonyOS Next中页面丢帧问题,可重点从以下方面进行优化:
-
布局与渲染优化
- 简化UI层级,避免过度嵌套,使用扁平化布局。
- 减少
Flex布局的复杂计算,对固定尺寸元素使用固定宽高。 - 对频繁更新的组件使用
@Reusable装饰器复用节点,减少创建开销。 - 图片资源使用合适尺寸并启用内存缓存,大图考虑分块加载或降采样。
-
数据与状态管理
- 使用
@State、@Prop等装饰器时,避免在短时间内频繁更新,可合并状态变更。 - 对于列表(
List)或网格(Grid)等长列表,确保启用cachedCount并配合LazyForEach实现按需渲染。 - 复杂计算或数据转换移至后台线程(
TaskPool或Worker),避免阻塞UI线程。
- 使用
-
动画与交互优化
- 使用系统提供的动画组件(如
animateTo)而非手动控制帧更新。 - 减少同时运行的动画数量,对连续动画考虑使用序列化执行。
- 交互事件(如滚动、拖拽)中避免同步执行耗时逻辑,可做异步防抖处理。
- 使用系统提供的动画组件(如
-
性能工具定位
- 使用DevEco Studio的ArkTS Profiler分析UI线程耗时,定位渲染瓶颈。
- 通过Smart Perf工具查看帧率曲线与丢帧点,结合代码审查对应操作。
- 检查是否存在同步的I/O操作、频繁GC或内存泄漏,这些会间接导致渲染阻塞。
若上述优化后仍丢帧,需进一步检查是否由特定组件或第三方库引起,可尝试隔离组件进行性能测试。

