Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
f8e480f4
D
Docs
项目概览
OpenHarmony
/
Docs
12 个月 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
f8e480f4
编写于
6月 30, 2023
作者:
O
openharmony_ci
提交者:
Gitee
6月 30, 2023
浏览文件
操作
浏览文件
下载
差异文件
!19234 应用性能最佳实践
Merge pull request !19234 from sunqi/master
上级
d0748960
5e6568a0
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
674 addition
and
0 deletion
+674
-0
zh-cn/application-dev/performance/Readme.md
zh-cn/application-dev/performance/Readme.md
+33
-0
zh-cn/application-dev/performance/figure/application-cold-start.png
...ication-dev/performance/figure/application-cold-start.png
+0
-0
zh-cn/application-dev/performance/improve-application-startup-and-response/improve-application-cold-start-speed.md
...rtup-and-response/improve-application-cold-start-speed.md
+110
-0
zh-cn/application-dev/performance/improve-application-startup-and-response/improve-application-response.md
...tion-startup-and-response/improve-application-response.md
+325
-0
zh-cn/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md
...me-loss-and-frame-freezing/reduce-animation-frame-loss.md
+142
-0
zh-cn/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md
...ame-loss-and-frame-freezing/reduce-view-nesting-levels.md
+64
-0
未找到文件。
zh-cn/application-dev/performance/Readme.md
0 → 100644
浏览文件 @
f8e480f4
# 应用性能最佳实践
本文简要介绍了用于在OpenHarmony上提升应用性能的最佳实践。
用户期望应用能够快速启动、及时响应、无卡顿,本文将提供提升应用启动和响应速度、减少丢帧卡顿的一些方法和案例供应用开发者参考。
-
提升应用启动和响应速度
-
[
提升应用冷启动速度
](
http://gitee.com/sqsyqqy/docs/blob/master/zh-cn/application-dev/performance/improve-application-startup-and-response/improve-application-cold-start-speed.md
)
应用启动时延是影响用户体验的关键要素。提升应用冷启动速度,建议在以下四个阶段进行优化:
1、应用进程创建&初始化阶段
2、Application&Ability初始化阶段
3、Ability生命周期阶段
4、加载绘制首页阶段
-
[
提升应用响应速度
](
http://gitee.com/sqsyqqy/docs/blob/master/zh-cn/application-dev/performance/improve-application-startup-and-response/improve-application-response.md
)
应用对用户的输入需要快速反馈,以提升交互体验。建议通过避免主线程被非UI任务阻塞、减少组件刷新的数量的方法来提升应用响应速度。
-
减少丢帧卡顿
-
[
减少视图嵌套层次
](
http://gitee.com/sqsyqqy/docs/blob/master/zh-cn/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md
)
应用将布局渲染到屏幕上的流畅度影响用户对质量的感知。建议移除多余的嵌套层次减少视图嵌套层次。
-
[
减少动画丢帧
](
http://gitee.com/sqsyqqy/docs/blob/master/zh-cn/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md
)
应用播放动画的流畅度是影响用户体验的重要因素。建议通过使用系统提供的动效API来减少动画丢帧。
zh-cn/application-dev/performance/figure/application-cold-start.png
0 → 100644
浏览文件 @
f8e480f4
12.6 KB
zh-cn/application-dev/performance/improve-application-startup-and-response/improve-application-cold-start-speed.md
0 → 100644
浏览文件 @
f8e480f4
# 提升应用冷启动速度
应用启动时延是影响用户体验的关键要素。当应用启动时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用, 这个启动方式就叫做冷启动。
## 分析应用冷启动耗时
OpenHarmony的应用冷启动过程大致可分成以下四个阶段:应用进程创建&初始化、Application&Ability初始化、Ability生命周期、加载绘制首页,如下图:
![
输入图片说明
](
../figure/application-cold-start.png
)
## 1、缩短应用进程创建&初始化阶段耗时
该阶段主要是系统完成应用进程的创建以及初始化的过程,包含了启动页图标(startWindowIcon)的解码。
### 设置合适分辨率的startWindowIcon
如果启动页图标分辨率过大,解码耗时会影响应用的启动速度,建议启动页图标分辨率不超过256像素
*
256像素,如下所示:
```
json
"abilities"
:
[
{
"name"
:
"EntryAbility"
,
"srcEntrance"
:
"./ets/entryability/EntryAbility.ts"
,
"description"
:
"$string:EntryAbility_desc"
,
"icon"
:
"$media:icon"
,
"label"
:
"$string:EntryAbility_label"
,
"startWindowIcon"
:
"$media:startWindowIcon"
,
//
在这里修改启动页图标,建议不要超过
256
像素x
256
像素
"startWindowBackground"
:
"$color:start_window_background"
,
"visible"
:
true
,
"skills"
:
[
{
"entities"
:
[
"entity.system.home"
],
"actions"
:
[
"action.system.home"
]
}
]
}
]
```
## 2、缩短Application&Ability初始化阶段耗时
该阶段主要是资源加载、虚拟机创建、Application&Ability相关对象的创建与初始化、依赖模块的加载等。
### 减少import的模块
应用代码执行前,应用程序必须找到并加载import的所有模块,应用程序加载的每个额外的第三方框架或者模块都会增加启动时间,耗时长短取决于加载的第三方框架或者模块的数量和大小。推荐开发者尽可能使用系统提供的模块,按需加载,来缩短应用程序的启动耗时。
## 3、缩短Ability生命周期阶段耗时
该阶段主要是Ability的启动生命周期,执行相应的生命周期回调。
### 避免在Ability生命周期回调接口进行耗时操作
在应用启动流程中,系统会执行Ability的生命周期回调函数。因此,不建议在这些回调函数中执行耗时过长的操作,耗时操作建议通过异步任务延迟处理或者放到其他线程执行。
在这些生命周期回调里,推荐开发者只做必要的操作,详情可以参考:
[
UIAbility组件生命周期
](
https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/application-models/uiability-lifecycle.md
)
## 4、缩短加载绘制首页阶段耗时
该阶段主要是加载首页内容、测量布局、刷新组件并绘制。
### 自定义组件生命周期回调接口里避免耗时操作
自定义组件的生命周期变更会调用相应的回调函数。
aboutToAppear函数会在创建自定义组件实例后,页面绘制之前执行,以下代码在aboutToAppear中对耗时长的计算任务进行了异步处理,避免在该接口执行该耗时操作,不阻塞页面绘制。
```
javascript
@
Entry
@
Component
struct
Index
{
@
State
private
text
:
string
=
undefined
;
private
count
:
number
=
undefined
;
aboutToAppear
()
{
this
.
computeTaskAsync
();
// 异步任务
this
.
text
=
"
hello world
"
;
}
build
()
{
Column
({
space
:
10
})
{
Text
(
this
.
text
).
fontSize
(
50
)
}
.
width
(
'
100%
'
)
.
height
(
'
100%
'
)
.
padding
(
10
)
}
computeTask
()
{
this
.
count
=
0
;
while
(
this
.
count
<
10000000
)
{
this
.
count
++
;
}
this
.
text
=
'
task complete
'
;
}
// 运算任务异步处理
private
computeTaskAsync
()
{
new
Promise
((
resolved
,
rejected
)
=>
{
setTimeout
(()
=>
{
// 这里使用setTimeout来实现异步延迟运行
this
.
computeTask
();
},
1000
)
})
}
}
```
\ No newline at end of file
zh-cn/application-dev/performance/improve-application-startup-and-response/improve-application-response.md
0 → 100644
浏览文件 @
f8e480f4
# 提升应用响应速度
应用对用户的输入需要快速反馈,以提升交互体验,因此本文提供了以下方法来提升应用响应速度。
-
避免主线程被非UI任务阻塞
-
减少组件刷新的数量
## 避免主线程被非UI任务阻塞
在应用响应用户输入期间,应用主线程应尽可能只执行UI任务(待显示数据的准备、可见视图组件的更新等),非UI的耗时任务(长时间加载的内容等)建议通过异步任务延迟处理或者分配到其他线程处理。
### 使用组件异步加载特性
OpenHarmony提供的Image组件默认生效异步加载特性,当应用在页面上展示一批本地图片的时候,会先显示空白占位块,当图片在其他线程加载完毕后,再替换占位块。这样图片加载就可以不阻塞页面的显示,给用户带来良好的交互体验。因此,只在加载图片耗时比较短的情况下建议下述代码。
```
javascript
@
Entry
@
Component
struct
ImageExample1
{
build
()
{
Column
()
{
Row
()
{
Image
(
'
resources/base/media/sss001.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
)
Image
(
'
resources/base/media/sss002.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
)
Image
(
'
resources/base/media/sss003.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
)
Image
(
'
resources/base/media/sss004.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
)
}
// 此处省略若干个Row容器,每个容器内都包含如上的若干Image组件
}
}
}
```
建议:在加载图片的耗时比较短的时候,通过异步加载的效果会大打折扣,建议配置Image的syncLoad属性。
```
javascript
@
Entry
@
Component
struct
ImageExample1
{
build
()
{
Column
()
{
Row
()
{
Image
(
'
resources/base/media/sss001.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
).
syncLoad
(
true
)
Image
(
'
resources/base/media/sss002.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
).
syncLoad
(
true
)
Image
(
'
resources/base/media/sss003.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
).
syncLoad
(
true
)
Image
(
'
resources/base/media/sss004.jpg
'
)
.
border
({
width
:
1
}).
borderStyle
(
BorderStyle
.
Dashed
).
aspectRatio
(
1
).
width
(
'
25%
'
).
height
(
'
12.5%
'
).
syncLoad
(
true
)
}
// 此处省略若干个Row容器,每个容器内都包含如上的若干Image组件
}
}
}
```
### 使用TaskPool线程池异步处理
OpenHarmony提供了
[
TaskPool线程池
](
https://gitee.com/sqsyqqy/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-taskpool.md
)
,相比worker线程,TaskPool提供了任务优先级设置、线程池自动管理机制,示例如下:
```
javascript
import
taskpool
from
'
@ohos.taskpool
'
;
@
Concurrent
function
computeTask
(
arr
:
string
[]):
string
[]
{
// 模拟一个计算密集型任务
let
count
=
0
;
while
(
count
<
100000000
)
{
count
++
;
}
return
arr
.
reverse
();
}
@
Entry
@
Component
struct
AspectRatioExample
{
@
State
children
:
string
[]
=
[
'
1
'
,
'
2
'
,
'
3
'
,
'
4
'
,
'
5
'
,
'
6
'
];
aboutToAppear
()
{
this
.
computeTaskInTaskPool
();
}
async
computeTaskInTaskPool
()
{
const
param
=
this
.
children
.
slice
();
let
task
=
new
taskpool
.
Task
(
computeTask
,
param
);
// @ts-ignore
this
.
children
=
await
taskpool
.
execute
(
task
);
}
build
()
{
// 组件布局
}
}
```
### 创建异步任务
以下代码展示了将一个长时间执行的非UI任务通过Promise声明成异步任务,主线程可以先进行用户反馈-绘制初始页面。等主线程空闲时,再执行异步任务。等到异步任务运行完毕后,重绘相关组件刷新页面。
```
javascript
@
Entry
@
Component
struct
AspectRatioExample
{
@
State
private
children
:
string
[]
=
[
'
1
'
,
'
2
'
,
'
3
'
,
'
4
'
,
'
5
'
,
'
6
'
];
private
count
:
number
=
undefined
;
aboutToAppear
()
{
this
.
computeTaskAsync
();
// 调用异步运算函数
}
// 模拟一个计算密集型任务
computeTask
()
{
this
.
count
=
0
;
while
(
this
.
count
<
100000000
)
{
this
.
count
++
;
}
this
.
children
=
this
.
children
.
reverse
();
}
computeTaskAsync
()
{
new
Promise
((
resolved
,
rejected
)
=>
{
setTimeout
(()
=>
{
// 这里使用setTimeout来实现异步延迟运行
this
.
computeTask
();
},
1000
)
})
}
build
()
{
// 组件布局
}
}
```
## 减少刷新的组件数量
应用刷新页面时需要尽可能减少刷新的组件数量,如果数量过多会导致主线程执行测量、布局的耗时过长,还会在自定义组件新建和销毁过程中,多次调用aboutToAppear()、aboutToDisappear()方法,增加主线程负载。
### 使用容器限制刷新范围
反例:如果容器内有组件被if条件包含,if条件结果变更会触发创建和销毁该组件,如果此时影响到容器的布局,该容器内所有组件都会刷新,导致主线程UI刷新耗时过长。
以下代码的Text('New Page')组件被状态变量isVisible控制,isVisible为true时创建,false时销毁。当isVisible发生变化时,Stack容器内的所有组件都会刷新:
```
javascript
@
Entry
@
Component
struct
StackExample
{
@
State
isVisible
:
boolean
=
false
;
build
()
{
Column
()
{
Stack
({
alignContent
:
Alignment
.
Top
})
{
Text
().
width
(
'
100%
'
).
height
(
'
70%
'
).
backgroundColor
(
0xd2cab3
)
.
align
(
Alignment
.
Center
).
textAlign
(
TextAlign
.
Center
);
// 此处省略100个相同的背景Text组件
if
(
this
.
isVisible
)
{
Text
(
'
New Page
'
).
height
(
"
100%
"
).
height
(
"
70%
"
).
backgroundColor
(
0xd2cab3
)
.
align
(
Alignment
.
Center
).
textAlign
(
TextAlign
.
Center
);
}
}
Button
(
"
press
"
).
onClick
(()
=>
{
this
.
isVisible
=
!
(
this
.
isVisible
);
})
}
}
}
```
建议:对于这种受状态变量控制的组件,在if外套一层容器,减少刷新范围。
```
javascript
@
Entry
@
Component
struct
StackExample
{
@
State
isVisible
:
boolean
=
false
;
build
()
{
Column
()
{
Stack
({
alignContent
:
Alignment
.
Top
})
{
Text
().
width
(
'
100%
'
).
height
(
'
70%
'
).
backgroundColor
(
0xd2cab3
)
.
align
(
Alignment
.
Center
).
textAlign
(
TextAlign
.
Center
);
// 此处省略100个相同的背景Text组件
Stack
()
{
if
(
this
.
isVisible
)
{
Text
(
'
New Page
'
).
height
(
"
100%
"
).
height
(
"
70%
"
).
backgroundColor
(
0xd2cab3
)
.
align
(
Alignment
.
Center
).
textAlign
(
TextAlign
.
Center
);
}
}.
width
(
'
100%
'
).
height
(
'
70%
'
)
}
Button
(
"
press
"
).
onClick
(()
=>
{
this
.
isVisible
=
!
(
this
.
isVisible
);
})
}
}
}
```
### 按需加载列表组件的元素
反例:this.arr中的每一项元素都被初始化和加载,数组中的元素有10000个,主线程执行耗时长。
```
javascript
@
Entry
@
Component
struct
MyComponent
{
@
State
arr
:
number
[]
=
Array
.
from
(
Array
(
10000
),
(
v
,
k
)
=>
k
);
build
()
{
List
()
{
ForEach
(
this
.
arr
,
(
item
:
number
)
=>
{
ListItem
()
{
Text
(
`item value:
${
item
}
`
)
}
},
(
item
:
number
)
=>
item
.
toString
())
}
}
}
```
建议:这种情况下用LazyForEach替换ForEach,LazyForEach一般只加载可见的元素,避免一次性初始化和加载所有元素。
```
javascript
class
BasicDataSource
implements
IDataSource
{
private
listeners
:
DataChangeListener
[]
=
[]
public
totalCount
():
number
{
return
0
}
public
getData
(
index
:
number
):
any
{
return
undefined
}
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
()
})
}
notifyDataAdd
(
index
:
number
):
void
{
this
.
listeners
.
forEach
(
listener
=>
{
listener
.
onDataAdd
(
index
)
})
}
notifyDataChange
(
index
:
number
):
void
{
this
.
listeners
.
forEach
(
listener
=>
{
listener
.
onDataChange
(
index
)
})
}
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
(
10000
),
(
v
,
k
)
=>
k
.
toString
());
public
totalCount
():
number
{
return
this
.
dataArray
.
length
}
public
getData
(
index
:
number
):
any
{
return
this
.
dataArray
[
index
]
}
public
addData
(
index
:
number
,
data
:
string
):
void
{
this
.
dataArray
.
splice
(
index
,
0
,
data
)
this
.
notifyDataAdd
(
index
)
}
public
pushData
(
data
:
string
):
void
{
this
.
dataArray
.
push
(
data
)
this
.
notifyDataAdd
(
this
.
dataArray
.
length
-
1
)
}
}
@
Entry
@
Component
struct
MyComponent
{
private
data
:
MyDataSource
=
new
MyDataSource
()
build
()
{
List
()
{
LazyForEach
(
this
.
data
,
(
item
:
string
)
=>
{
ListItem
()
{
Text
(
item
).
fontSize
(
20
).
margin
({
left
:
10
})
}
},
item
=>
item
)
}
}
}
```
\ No newline at end of file
zh-cn/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-animation-frame-loss.md
0 → 100644
浏览文件 @
f8e480f4
# 减少动画丢帧
在播放动画或者生成动画时,画面产生停滞而导致帧率过低的现象,称为动画丢帧。
播放动画时,系统需要在一个刷新周期内完成动画变化曲线的计算,完成组件布局绘制等操作。建议使用系统提供的动画接口,只需设置曲线类型、终点位置、时长等信息,就能够满足常用的动画功能,减少UI主线程的负载。
反例:应用使用了自定义动画,动画曲线计算过程很容易引起UI线程高负载,易导致丢帧。
```
javascript
@
Entry
@
Component
struct
AttrAnimationExample
{
@
State
widthSize
:
number
=
200
@
State
heightSize
:
number
=
100
@
State
flag
:
boolean
=
true
computeSize
()
{
let
duration
=
2000
let
period
=
16
let
widthSizeEnd
=
undefined
let
heightSizeEnd
=
undefined
if
(
this
.
flag
)
{
widthSizeEnd
=
100
heightSizeEnd
=
50
}
else
{
widthSizeEnd
=
200
heightSizeEnd
=
100
}
let
doTimes
=
duration
/
period
let
deltaHeight
=
(
heightSizeEnd
-
this
.
heightSize
)
/
doTimes
let
deltaWeight
=
(
widthSizeEnd
-
this
.
widthSize
)
/
doTimes
for
(
let
i
=
1
;
i
<=
doTimes
;
i
++
)
{
let
t
=
period
*
(
i
);
setTimeout
(()
=>
{
this
.
heightSize
=
this
.
heightSize
+
deltaHeight
this
.
widthSize
=
this
.
widthSize
+
deltaWeight
},
t
)
}
this
.
flag
=
!
this
.
flag
}
build
()
{
Column
()
{
Button
(
'
click me
'
)
.
onClick
(()
=>
{
let
delay
=
500
setTimeout
(()
=>
{
this
.
computeSize
()
},
delay
)
})
.
width
(
this
.
widthSize
).
height
(
this
.
heightSize
).
backgroundColor
(
0x317aff
)
}.
width
(
'
100%
'
).
margin
({
top
:
5
})
}
}
```
## 使用系统提供的属性动效API
建议:通过系统提供的属性动效API实现上述动效功能。
```
javascript
@
Entry
@
Component
struct
AttrAnimationExample
{
@
State
widthSize
:
number
=
200
@
State
heightSize
:
number
=
100
@
State
flag
:
boolean
=
true
build
()
{
Column
()
{
Button
(
'
click me
'
)
.
onClick
((
event
:
ClickEvent
)
=>
{
if
(
this
.
flag
)
{
this
.
widthSize
=
100
this
.
heightSize
=
50
}
else
{
this
.
widthSize
=
200
this
.
heightSize
=
100
}
this
.
flag
=
!
this
.
flag
})
.
width
(
this
.
widthSize
).
height
(
this
.
heightSize
).
backgroundColor
(
0x317aff
)
.
animation
({
duration
:
2000
,
// 动画时长
curve
:
Curve
.
Linear
,
// 动画曲线
delay
:
500
,
// 动画延迟
iterations
:
1
,
// 播放次数
playMode
:
PlayMode
.
Normal
// 动画模式
})
// 对Button组件的宽高属性进行动画配置
}.
width
(
'
100%
'
).
margin
({
top
:
5
})
}
}
```
更详细的API文档请参考:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-animatorproperty.md
## 使用系统提供的显式动效API
建议:通过系统提供的显式动效API实现上述动效功能。
```
javascript
@
Entry
@
Component
struct
AnimateToExample
{
@
State
widthSize
:
number
=
200
;
@
State
heightSize
:
number
=
100
;
@
State
flag
:
boolean
=
true
;
build
()
{
Column
()
{
Button
(
'
click me
'
)
.
onClick
((
event
:
ClickEvent
)
=>
{
if
(
this
.
flag
)
{
animateTo
({
duration
:
2000
,
// 动画时长
curve
:
Curve
.
Linear
,
// 动画曲线
delay
:
500
,
// 动画延迟
iterations
:
1
,
// 播放次数
playMode
:
PlayMode
.
Normal
// 动画模式
},
()
=>
{
this
.
widthSize
=
100
;
this
.
heightSize
=
50
;
})
}
else
{
animateTo
({
duration
:
2000
,
// 动画时长
curve
:
Curve
.
Linear
,
// 动画曲线
delay
:
500
,
// 动画延迟
iterations
:
1
,
// 播放次数
playMode
:
PlayMode
.
Normal
// 动画模式
},
()
=>
{
this
.
widthSize
=
200
;
this
.
heightSize
=
100
;
})
}
this
.
flag
=
!
this
.
flag
;
})
.
width
(
this
.
widthSize
).
height
(
this
.
heightSize
).
backgroundColor
(
0x317aff
)
}.
width
(
'
100%
'
).
margin
({
top
:
5
})
}
}
```
更详细的API文档请参考:https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/arkui-ts/ts-explicit-animation.md
\ No newline at end of file
zh-cn/application-dev/performance/reduce-frame-loss-and-frame-freezing/reduce-view-nesting-levels.md
0 → 100644
浏览文件 @
f8e480f4
# 减少视图嵌套层次
视图的嵌套层次会影响应用的性能。在屏幕刷新率为120Hz的设备上,每8.3ms刷新一帧,如果视图的嵌套层次多,可能会导致没法在8.3ms内完成一次屏幕刷新,就会造成丢帧卡顿,影响用户体验。因此推荐开发者移除多余的嵌套层次,缩短组件刷新耗时。
## 移除多余的嵌套层次
反例:使用了Grid来实现一个网格,但是在外层套了3层stack容器,导致组件刷新和渲染耗时长。
```
javascript
@
Entry
@
Component
struct
AspectRatioExample
{
@
State
children
:
Number
[]
=
Array
.
from
(
Array
(
900
),
(
v
,
k
)
=>
k
);
build
()
{
Scroll
()
{
Grid
()
{
ForEach
(
this
.
children
,
(
item
)
=>
{
GridItem
()
{
Stack
()
{
Stack
()
{
Stack
()
{
Text
(
item
.
toString
())
}
}
}
}
},
item
=>
item
)
}
.
columnsTemplate
(
'
1fr 1fr 1fr 1fr
'
)
.
columnsGap
(
0
)
.
rowsGap
(
0
)
.
size
({
width
:
"
100%
"
,
height
:
"
100%
"
})
}
}
}
```
建议:通过减少冗余的Stack容器嵌套,每个GridItem的组件数比上面少了3个,缩短了组件刷新与渲染耗时。
```
javascript
// xxx.ets
@
Entry
@
Component
struct
AspectRatioExample
{
@
State
children
:
Number
[]
=
Array
.
from
(
Array
(
900
),
(
v
,
k
)
=>
k
);
build
()
{
Scroll
()
{
Grid
()
{
ForEach
(
this
.
children
,
(
item
)
=>
{
GridItem
()
{
Text
(
item
.
toString
())
}
},
item
=>
item
)
}
.
columnsTemplate
(
'
1fr 1fr 1fr 1fr
'
)
.
columnsGap
(
0
)
.
rowsGap
(
0
)
.
size
({
width
:
"
100%
"
,
height
:
"
100%
"
})
}
}
}
```
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录