首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

鸿蒙(AIP Beta5版)开发实战-性能提升的其他方法

  • 25-03-03 07:01
  • 2369
  • 11839
blog.csdn.net

开发者若使用低性能的代码实现功能场景可能不会影响应用的正常运行,但却会对应用的性能造成负面影响。本章节列举出了一些可提升性能的场景供开发者参考,以避免应用实现上带来的性能劣化。

设置List组件的宽高

在使用Scroll容器组件嵌套List组件加载长列表时,若不指定List的宽高尺寸,则默认全部加载。

说明:

Scroll嵌套List时:

  • List没有设置宽高,会布局List的所有子组件。

  • List设置宽高,会布局List显示区域内的子组件。

  • List使用ForEach加载子组件时,无论是否设置List的宽高,都会加载所有子组件。

  • List使用LazyForEach加载子组件时,没有设置List的宽高,会加载所有子组件,设置了List的宽高,会加载List显示区域内的子组件。

  1. class BasicDataSource implements IDataSource {
  2. private listeners: DataChangeListener[] = [];
  3. private originDataArray: string[] = [];
  4. public totalCount(): number {
  5. return 0;
  6. }
  7. public getData(index: number): string {
  8. return this.originDataArray[index];
  9. }
  10. registerDataChangeListener(listener: DataChangeListener): void {
  11. if (this.listeners.indexOf(listener) < 0) {
  12. console.info('add listener');
  13. this.listeners.push(listener);
  14. }
  15. }
  16. unregisterDataChangeListener(listener: DataChangeListener): void {
  17. const pos = this.listeners.indexOf(listener);
  18. if (pos >= 0) {
  19. console.info('remove listener');
  20. this.listeners.splice(pos, 1);
  21. }
  22. }
  23. notifyDataReload(): void {
  24. this.listeners.forEach(listener => {
  25. listener.onDataReloaded();
  26. })
  27. }
  28. notifyDataAdd(index: number): void {
  29. this.listeners.forEach(listener => {
  30. listener.onDataAdd(index);
  31. })
  32. }
  33. notifyDataChange(index: number): void {
  34. this.listeners.forEach(listener => {
  35. listener.onDataChange(index);
  36. })
  37. }
  38. notifyDataDelete(index: number): void {
  39. this.listeners.forEach(listener => {
  40. listener.onDataDelete(index);
  41. })
  42. }
  43. notifyDataMove(from: number, to: number): void {
  44. this.listeners.forEach(listener => {
  45. listener.onDataMove(from, to);
  46. })
  47. }
  48. }
  49. class MyDataSource extends BasicDataSource {
  50. private dataArray: Array<string> = new Array(100).fill('test');
  51. public totalCount(): number {
  52. return this.dataArray.length;
  53. }
  54. public getData(index: number): string {
  55. return this.dataArray[index];
  56. }
  57. public addData(index: number, data: string): void {
  58. this.dataArray.splice(index, 0, data);
  59. this.notifyDataAdd(index);
  60. }
  61. public pushData(data: string): void {
  62. this.dataArray.push(data);
  63. this.notifyDataAdd(this.dataArray.length - 1);
  64. }
  65. }
  66. @Entry
  67. @Component
  68. struct MyComponent {
  69. private data: MyDataSource = new MyDataSource();
  70. build() {
  71. Scroll() {
  72. List() {
  73. LazyForEach(this.data, (item: string, index: number ) => {
  74. ListItem() {
  75. Row() {
  76. Text('item value: ' + item + (index + 1)).fontSize(20).margin(10)
  77. }
  78. }
  79. })
  80. }
  81. }
  82. }
  83. }

因此,此场景下建议设置List子组件的宽高。

  1. class BasicDataSource implements IDataSource {
  2. private listeners: DataChangeListener[] = [];
  3. private originDataArray: string[] = [];
  4. public totalCount(): number {
  5. return 0;
  6. }
  7. public getData(index: number): string {
  8. return this.originDataArray[index];
  9. }
  10. registerDataChangeListener(listener: DataChangeListener): void {
  11. if (this.listeners.indexOf(listener) < 0) {
  12. console.info('add listener');
  13. this.listeners.push(listener);
  14. }
  15. }
  16. unregisterDataChangeListener(listener: DataChangeListener): void {
  17. const pos = this.listeners.indexOf(listener);
  18. if (pos >= 0) {
  19. console.info('remove listener')
  20. this.listeners.splice(pos, 1);
  21. }
  22. }
  23. notifyDataReload(): void {
  24. this.listeners.forEach(listener => {
  25. listener.onDataReloaded();
  26. })
  27. }
  28. notifyDataAdd(index: number): void {
  29. this.listeners.forEach(listener => {
  30. listener.onDataAdd(index);
  31. })
  32. }
  33. notifyDataChange(index: number): void {
  34. this.listeners.forEach(listener => {
  35. listener.onDataChange(index);
  36. })
  37. }
  38. notifyDataDelete(index: number): void {
  39. this.listeners.forEach(listener => {
  40. listener.onDataDelete(index);
  41. })
  42. }
  43. notifyDataMove(from: number, to: number): void {
  44. this.listeners.forEach(listener => {
  45. listener.onDataMove(from, to);
  46. })
  47. }
  48. }
  49. class MyDataSource extends BasicDataSource {
  50. private dataArray: Array<string> = new Array(100).fill('test')
  51. public totalCount(): number {
  52. return this.dataArray.length;
  53. }
  54. public getData(index: number): string {
  55. return this.dataArray[index];
  56. }
  57. public addData(index: number, data: string): void {
  58. this.dataArray.splice(index, 0, data);
  59. this.notifyDataAdd(index);
  60. }
  61. public pushData(data: string): void {
  62. this.dataArray.push(data);
  63. this.notifyDataAdd(this.dataArray.length - 1);
  64. }
  65. }
  66. @Entry
  67. @Component
  68. struct MyComponent {
  69. private data: MyDataSource = new MyDataSource();
  70. build() {
  71. Scroll() {
  72. List() {
  73. LazyForEach(this.data, (item: string, index: number) => {
  74. ListItem() {
  75. Text('item value: ' + item + (index + 1)).fontSize(20).margin(10)
  76. }.width('100%')
  77. })
  78. }.width('100%').height(500)
  79. }.backgroundColor(Color.Pink)
  80. }
  81. }

list1

使用SmartPerf Host工具分别抓取List不设置宽高时和设置宽高时的trace数据。

List不设置宽高:

list-trace-01

List设置宽高:

list-trace-02

从trace图可以看出,List不设置宽高时100个子组件全部参与布局,布局时间46.62ms。而给List设置宽高后只有给定高度内的12个子组件参与布局,布局时间减少到8.51ms,大幅提升了首次加载时的性能。

使用Column/Row替代Flex

由于Flex容器组件默认情况下存在shrink导致二次布局,这会在一定程度上造成页面渲染上的性能劣化。

  1. @Entry
  2. @Component
  3. struct FlexBuild {
  4. private data: string[] = new Array(20).fill('');
  5. build() {
  6. Flex({ direction: FlexDirection.Column }) {
  7. Flex({ direction: FlexDirection.Column }) {
  8. Flex({ direction: FlexDirection.Column }) {
  9. Flex({ direction: FlexDirection.Column }) {
  10. Flex({ direction: FlexDirection.Column }) {
  11. ForEach(this.data, (item: string, index: number) => {
  12. Text(`Item ${index}`)
  13. .width('100%')
  14. .textAlign(TextAlign.Center)
  15. })
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }

上述代码可将Flex替换为Column、Row,在保证实现的页面布局效果相同的前提下避免Flex二次布局带来的负面影响。

  1. @Entry
  2. @Component
  3. struct ColumnAndRowBuild {
  4. private data: string[] = new Array(20).fill('');
  5. build() {
  6. Row() {
  7. Row() {
  8. Row() {
  9. Row() {
  10. Column() {
  11. ForEach(this.data, (item: string, index: number) => {
  12. Text(`Item ${index}`)
  13. .width('100%')
  14. .textAlign(TextAlign.Center)
  15. })
  16. }
  17. }
  18. }
  19. }
  20. }
  21. }
  22. }

flex1

使用SmartPerf Host抓取上述两种不同布局方式示例程序的trace数据,对比其性能消耗,如下表所示。

对比指标Flex布局Column/Row
Build耗时(ms)4.272.51
Measure耗时(ms)2.981.04
Layout耗时(ms)0.340.24

可以看出布局深度和节点数相同的情况下,Flex的性能明显低于Column和Row容器,此时使用Column/Row替换Flex可以显著减少应用布局的性能消耗。

减少应用滑动白块

应用通过增大List/Grid控件的cachedCount参数,调整UI的加载范围。cachedCount表示屏幕外List/Grid预加载item的个数。
如果需要请求网络图片,可以在item滑动到屏幕显示之前,提前下载好内容,从而减少滑动白块。
如下是使用cachedCount参数的例子:

  1. @Entry
  2. @Component
  3. struct MyComponent {
  4. private source: MyDataSource = new MyDataSource();
  5. build() {
  6. List() {
  7. LazyForEach(this.source, (item:string) => {
  8. ListItem() {
  9. Text("Hello" + item)
  10. .fontSize(50)
  11. .onAppear(() => {
  12. console.log("appear:" + item)
  13. })
  14. }
  15. })
  16. }.cachedCount(3) // 扩大数值appear日志范围会变大
  17. }
  18. }
  19. class MyDataSource implements IDataSource {
  20. data: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
  21. public totalCount(): number {
  22. return this.data.length
  23. }
  24. public getData(index: number): number {
  25. return this.data[index]
  26. }
  27. registerDataChangeListener(listener: DataChangeListener): void {
  28. }
  29. unregisterDataChangeListener(listener: DataChangeListener): void {
  30. }
  31. }

list2

使用说明: cachedCount的增加会增大UI的cpu、内存开销。使用时需要根据实际情况,综合性能和用户体验进行调整。

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为资料太多,太杂,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)文档用来跟着学习是非常有必要的。 

为了确保高效学习,建议规划清晰的学习路线,涵盖以下关键阶段:


 鸿蒙(HarmonyOS NEXT)最新学习路线

​

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频学习教程+学习PDF文档

HarmonyOS Next 最新全套视频教程

  纯血版鸿蒙全套学习文档(面试、文档、全套视频等)              

​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线

文章知识点与官方知识档案匹配,可进一步学习相关知识
CS入门技能树Linux入门初识Linux42834 人正在系统学习中
鸿蒙NEXT全套学习资料
微信名片
注:本文转载自blog.csdn.net的让开,我要吃人了的文章"https://blog.csdn.net/weixin_55362248/article/details/141679479"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top