05 HarmonyOS NEXT高效编程秘籍:Arkts函数调用与声明优化深度解析 ...

打印 上一主题 下一主题

主题 1729|帖子 1729|积分 5187


   温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!
  
  
概述

本篇文章,将焦点转向函数调用与函数声明的优化策略。在HarmonyOS NEXT API12+的开辟过程中,函数的精准界说与高效调用是提拔应用性能的关键所在。本文将通过一个具体计算器应用的实例,逐一发表几种经过实践查验的优化技巧,旨在引导开辟者如何编写出更加高效的代码,从而优化应用性能和用户体验。
函数调用优化

声明参数要和实际的参数同等

在HarmonyOS NEXT开辟中,声明的参数要和实际的传入参数个数及范例同等,否则会导致运行时走入慢速路径,影响性能。
反例

  1. @Entry
  2. @Component
  3. struct CalculatorBad {
  4.   @State result: string = '0';
  5.   // 参数声明与实际使用不一致的计算函数
  6.   calculate(operation: string, a: number, b: number) {
  7.     switch(operation) {
  8.       case 'add':
  9.         // 错误:传入了多余的参数
  10.         return this.add(a, b, 0);
  11.       case 'subtract':
  12.         // 错误:参数类型不匹配
  13.         return this.subtract(a.toString(), b.toString());
  14.       default:
  15.         return 0;
  16.     }
  17.   }
  18.   // 基础数学运算函数
  19.   add(a: number, b: number) {
  20.     return a + b;
  21.   }
  22.   subtract(a: number, b: number) {
  23.     return a - b;
  24.   }
  25.   build() {
  26.     Column() {
  27.       Text(this.result)
  28.         .fontSize(30)
  29.         .margin(20)
  30.       
  31.       Row() {
  32.         Button('计算示例')
  33.           .onClick(() => {
  34.             // 错误调用方式
  35.             this.result = this.calculate('add', 1, 2, 3).toString();
  36.           })
  37.       }
  38.     }
  39.     .width('100%')
  40.     .height('100%')
  41.   }
  42. }
复制代码
正例

  1. @Entry
  2. @Component
  3. struct CalculatorGood {
  4.   @State result: string = '0';
  5.   @State num1: string = '';
  6.   @State num2: string = '';
  7.   // 使用接口定义计算器操作
  8.   interface Operation {
  9.     calculate(a: number, b: number): number;
  10.     symbol: string;
  11.   }
  12.   // 预定义所有操作类型
  13.   private operations: Record<string, Operation> = {
  14.     add: {
  15.       calculate: (a: number, b: number): number => a + b,
  16.       symbol: '+'
  17.     },
  18.     subtract: {
  19.       calculate: (a: number, b: number): number => a - b,
  20.       symbol: '-'
  21.     }
  22.   };
  23.   // 参数类型和数量完全匹配的计算函数
  24.   calculate(operation: string): void {
  25.     const op = this.operations[operation];
  26.     if (!op) return;
  27.     const a = Number(this.num1);
  28.     const b = Number(this.num2);
  29.    
  30.     // 参数类型和数量完全匹配
  31.     this.result = op.calculate(a, b).toString();
  32.   }
  33.   build() {
  34.     Column() {
  35.       // 计算结果显示
  36.       Text(this.result)
  37.         .fontSize(30)
  38.         .margin(20)
  39.       
  40.       // 输入框
  41.       TextInput({ placeholder: '第一个数字' })
  42.         .width('80%')
  43.         .margin(10)
  44.         .onChange((value: string) => {
  45.           this.num1 = value;
  46.         })
  47.       
  48.       TextInput({ placeholder: '第二个数字' })
  49.         .width('80%')
  50.         .margin(10)
  51.         .onChange((value: string) => {
  52.           this.num2 = value;
  53.         })
  54.       
  55.       // 操作按钮
  56.       Row() {
  57.         ForEach(Object.keys(this.operations), (key: string) => {
  58.           Button(this.operations[key].symbol)
  59.             .margin(10)
  60.             .onClick(() => {
  61.               // 正确的参数传递方式
  62.               this.calculate(key);
  63.             })
  64.         })
  65.       }
  66.       .margin(20)
  67.     }
  68.     .width('100%')
  69.     .height('100%')
  70.     .justifyContent(FlexAlign.Center)
  71.   }
  72. }
复制代码
函数内部变量尽量使用参数传递

在HarmonyOS NEXT开辟中,能传递参数的尽量传递参数,不要使用闭包。闭包作为参数会多一次闭包创建和访问,影响性能。
反例

  1. @Component
  2. struct CalculationHistoryBad {
  3.   // 全局历史记录
  4.   private static history: string[] = [];
  5.   // 错误示例:使用闭包访问外部变量
  6.   addToHistory() {
  7.     // 通过闭包访问静态变量,性能较差
  8.     CalculationHistoryBad.history.push(`计算时间: ${new Date().toLocaleString()}`);
  9.   }
  10.   clearHistory() {
  11.     // 通过闭包访问静态变量,性能较差
  12.     CalculationHistoryBad.history = [];
  13.   }
  14.   build() {
  15.     Column() {
  16.       // 通过闭包访问历史记录
  17.       ForEach(CalculationHistoryBad.history, (item: string) => {
  18.         Text(item)
  19.           .fontSize(16)
  20.           .margin(5)
  21.       })
  22.     }
  23.   }
  24. }
复制代码
正例

  1. @Component
  2. struct CalculationHistoryGood {
  3.   @State history: string[] = [];
  4.   // 正确示例:通过参数传递数据
  5.   addToHistory(record: string): void {
  6.     // 通过参数传递,性能更好
  7.     this.history = [...this.history, record];
  8.   }
  9.   // 使用参数传递新的历史记录状态
  10.   updateHistory(newHistory: string[]): void {
  11.     this.history = newHistory;
  12.   }
  13.   build() {
  14.     Column() {
  15.       // 直接使用组件状态
  16.       ForEach(this.history, (item: string) => {
  17.         Text(item)
  18.           .fontSize(16)
  19.           .margin(5)
  20.       })
  21.       Button('添加记录')
  22.         .onClick(() => {
  23.           // 通过参数传递数据
  24.           this.addToHistory(`计算时间: ${new Date().toLocaleString()}`);
  25.         })
  26.       Button('清空记录')
  27.         .onClick(() => {
  28.           // 通过参数传递空数组
  29.           this.updateHistory([]);
  30.         })
  31.     }
  32.   }
  33. }
复制代码
函数与类声明优化

避免动态声明function与class

在HarmonyOS NEXT开辟中,动态声明function和class会导致每次调用都重新创建,对内存和性能都会有影响。
反例

  1. @Entry
  2. @Component
  3. struct CalculatorFactoryBad {
  4.   @State result: string = '0';
  5.   // 错误示例:动态创建计算器类
  6.   createCalculator(type: string) {
  7.     if (type === 'scientific') {
  8.       // 每次调用都会创建新的类,性能差
  9.       return class ScientificCalculator {
  10.         sin(x: number): number {
  11.           return Math.sin(x);
  12.         }
  13.         cos(x: number): number {
  14.           return Math.cos(x);
  15.         }
  16.       }
  17.     } else {
  18.       // 每次调用都会创建新的类,性能差
  19.       return class BasicCalculator {
  20.         add(a: number, b: number): number {
  21.           return a + b;
  22.         }
  23.         subtract(a: number, b: number): number {
  24.           return a - b;
  25.         }
  26.       }
  27.     }
  28.   }
  29.   build() {
  30.     Column() {
  31.       Text(this.result)
  32.         .fontSize(30)
  33.       Button('创建计算器')
  34.         .onClick(() => {
  35.           // 每次点击都会创建新的类实例
  36.           const Calculator = this.createCalculator('scientific');
  37.           const calc = new Calculator();
  38.           this.result = calc.sin(30).toString();
  39.         })
  40.     }
  41.   }
  42. }
复制代码
正例

  1. // 预定义计算器接口
  2. interface ICalculator {
  3.   calculate(x: number, y?: number): number;
  4.   getType(): string;
  5. }
  6. // 预定义所有计算器类
  7. class ScientificCalculator implements ICalculator {
  8.   private static instance: ScientificCalculator;
  9.   // 使用单例模式
  10.   static getInstance(): ScientificCalculator {
  11.     if (!ScientificCalculator.instance) {
  12.       ScientificCalculator.instance = new ScientificCalculator();
  13.     }
  14.     return ScientificCalculator.instance;
  15.   }
  16.   calculate(x: number): number {
  17.     return Math.sin(x);
  18.   }
  19.   getType(): string {
  20.     return '科学计算器';
  21.   }
  22. }
  23. class BasicCalculator implements ICalculator {
  24.   private static instance: BasicCalculator;
  25.   static getInstance(): BasicCalculator {
  26.     if (!BasicCalculator.instance) {
  27.       BasicCalculator.instance = new BasicCalculator();
  28.     }
  29.     return BasicCalculator.instance;
  30.   }
  31.   calculate(x: number, y: number): number {
  32.     return x + y;
  33.   }
  34.   getType(): string {
  35.     return '基础计算器';
  36.   }
  37. }
  38. @Entry
  39. @Component
  40. struct CalculatorFactoryGood {
  41.   @State result: string = '0';
  42.   @State currentType: string = 'basic';
  43.   // 工厂函数返回预定义的类实例
  44.   getCalculator(type: string): ICalculator {
  45.     switch (type) {
  46.       case 'scientific':
  47.         return ScientificCalculator.getInstance();
  48.       default:
  49.         return BasicCalculator.getInstance();
  50.     }
  51.   }
  52.   build() {
  53.     Column() {
  54.       Text(this.result)
  55.         .fontSize(30)
  56.         .margin(20)
  57.       Text(`当前模式: ${this.getCalculator(this.currentType).getType()}`)
  58.         .fontSize(20)
  59.         .margin(10)
  60.       Row() {
  61.         Button('基础模式')
  62.           .margin(10)
  63.           .onClick(() => {
  64.             this.currentType = 'basic';
  65.             const calc = this.getCalculator('basic');
  66.             this.result = calc.calculate(1, 2).toString();
  67.           })
  68.         Button('科学模式')
  69.           .margin(10)
  70.           .onClick(() => {
  71.             this.currentType = 'scientific';
  72.             const calc = this.getCalculator('scientific');
  73.             this.result = calc.calculate(30).toString();
  74.           })
  75.       }
  76.     }
  77.     .width('100%')
  78.     .height('100%')
  79.     .justifyContent(FlexAlign.Center)
  80.   }
  81. }
复制代码
性能测试示例



下面是一个简朴的性能测试组件,用于比较差别实现方式的性能差别:
  1.   // performance-test.ets
  2. @Component
  3. export struct PerformanceTest {
  4.     @State testResults: string = '';
  5.     aboutToAppear() {
  6.         this.runPerformanceTests();
  7.     }
  8.     // 性能测试函数
  9.     async runPerformanceTests() {
  10.         const iterations = 100000;
  11.         const testArray = [1, 2, 3, 4, 5];
  12.         // 测试1: 使用闭包
  13.         const startTime1 = new Date().getTime();
  14.         let sum1 = 0;
  15.         const sumWithClosure = () => {
  16.             for (let i = 0; i < testArray.length; i++) {
  17.                 sum1 += testArray[i];
  18.             }
  19.             return sum1;
  20.         }
  21.         for (let i = 0; i < iterations; i++) {
  22.             sumWithClosure();
  23.         }
  24.         const endTime1 = new Date().getTime();
  25.         // 测试2: 使用参数传递
  26.         const startTime2 = new Date().getTime();
  27.         let sum2 = 0;
  28.         const sumWithParams = (arr: number[]): number => {
  29.             let localSum = 0;
  30.             for (let i = 0; i < arr.length; i++) {
  31.                 localSum += arr[i];
  32.             }
  33.             return localSum;
  34.         }
  35.         for (let i = 0; i < iterations; i++) {
  36.             sum2 = sumWithParams(testArray);
  37.         }
  38.         const endTime2 = new Date().getTime();
  39.         // 更新测试结果
  40.         this.testResults = `
  41. 闭包方式耗时: ${endTime1 - startTime1}ms
  42. 参数传递耗时: ${endTime2 - startTime2}ms
  43. 闭包结果: ${sum1}
  44. 参数传递结果: ${sum2}
  45.     `;
  46.     }
  47.     build() {
  48.         Column() {
  49.             Text('性能测试结果')
  50.                 .fontSize(24)
  51.                 .margin(20)
  52.             Text(this.testResults)
  53.                 .fontSize(16)
  54.                 .margin(20)
  55.             // 添加更多测试用例
  56.             Button('运行更多测试')
  57.                 .onClick(() => {
  58.                     this.runMoreTests();
  59.                 })
  60.                 .margin(20)
  61.         }
  62.         .width('100%')
  63.             .height('100%')
  64.             .justifyContent(FlexAlign.Center)
  65.     }
  66.     // 更多性能测试用例
  67.     async runMoreTests() {
  68.         const iterations = 100000;
  69.         const testArray = [1, 2, 3, 4, 5];
  70.         // 测试3: 动态函数声明
  71.         const startTime3 = new Date().getTime();
  72.         let sum3 = 0;
  73.         for (let i = 0; i < iterations; i++) {
  74.             const dynamicSum =  (arr: number[]): number=> {
  75.                 let localSum = 0;
  76.                 for (let j = 0; j < arr.length; j++) {
  77.                     localSum += arr[j];
  78.                 }
  79.                 return localSum;
  80.             };
  81.             sum3 = dynamicSum(testArray);
  82.         }
  83.         const endTime3 = new Date().getTime();
  84.         // 测试4: 预定义函数
  85.         const startTime4 = new Date().getTime();
  86.         let sum4 = 0;
  87.         const predefinedSum = (arr: number[]): number => {
  88.             let localSum = 0;
  89.             for (let i = 0; i < arr.length; i++) {
  90.                 localSum += arr[i];
  91.             }
  92.             return localSum;
  93.         };
  94.         for (let i = 0; i < iterations; i++) {
  95.             sum4 = predefinedSum(testArray);
  96.         }
  97.         const endTime4 = new Date().getTime();
  98.         // 更新测试结果
  99.         this.testResults += `
  100. 动态函数声明耗时: ${endTime3 - startTime3}ms
  101. 预定义函数耗时: ${endTime4 - startTime4}ms
  102. 动态函数结果: ${sum3}
  103. 预定义函数结果: ${sum4}
  104.     `;
  105.     }
  106. }
复制代码
性能测试效果分析

通过上述性能测试组件,我们可以得出以下结论:

  • 参数传递 vs 闭包:使用参数传递的方式比使用闭包访问外部变量的性能更好,因为闭包需要额外的创建和访问成本。
  • 预界说函数 vs 动态函数:预界说函数的性能明显优于动态声明的函数,因为动态声明会在每次调用时重新创建函数对象。
  • 内存使用:使用参数传递和预界说函数的方式不仅执行速率更快,而且内存使用也更加高效,因为避免了额外的闭包对象和动态函数对象的创建。
最佳实践建议

基于上述性能测试效果,我们建议在HarmonyOS NEXT开辟中遵照以下最佳实践:

  • 函数参数传递

    • 优先使用参数传递而不是闭包访问外部变量
    • 确保参数范例和数量的同等性
    • 避免使用可选参数,而是使用明确的函数重载

  • 函数声明方式

    • 使用预界说的函数而不是动态声明
    • 接纳单例模式管理类实例
    • 避免在循环或条件语句中声明函数

  • 性能优化技巧

    • 使用TypeScript的范例系统确保范例安全
    • 避免不必要的对象创建和内存分配
    • 利用接口和范例界说进步代码的可维护性

通过遵照这些最佳实践,我们可以编写出更高效、更可靠的HarmonyOS NEXT应用步伐。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表