及时做APP开发实战(十一)-性能优化实践

及时做APP开发实战(十一)-性能优化实践

本文将详细介绍HarmonyOS应用性能优化的关键实践,包括定时器销毁和不可变数组操作。

一、性能优化概述

1.1 为什么需要性能优化

复制代码
┌─────────────────────────────────────┐
│          性能问题影响                │
├─────────────────────────────────────┤
│  内存泄漏 → 应用卡顿、崩溃           │
│  UI不刷新 → 数据不同步、体验差       │
│  长列表卡顿 → 滑动不流畅            │
│  后台耗电 → 用户投诉、卸载           │
└─────────────────────────────────────┘

1.2 优化目标

优化项 目标 效果
定时器销毁 杜绝内存泄漏 后台无无效计时
不可变数组 UI正确刷新 数据实时同步
懒加载 减少渲染开销 长列表流畅

二、定时器销毁优化

2.1 问题分析

【图1:定时器泄漏场景】

复制代码
┌─────────────────────────────────────┐
│          定时器生命周期              │
├─────────────────────────────────────┤
│  [页面进入]                          │
│      ↓                              │
│  [启动定时器] setInterval()          │
│      ↓                              │
│  [用户退出页面]                       │
│      ↓                              │
│  ❌ 定时器未销毁 → 后台持续运行       │
│      ↓                              │
│  ❌ 内存泄漏 + 耗电                   │
└─────────────────────────────────────┘

2.2 正确实现方式

typescript 复制代码
@Entry
@Component
struct PomodoroPage {
  // 定时器ID
  private timerId: number = -1;
  
  // 启动计时器
  startTimer() {
    if (this.timerId === -1) {
      this.timerId = setInterval(() => {
        // 计时逻辑
      }, 1000);
    }
  }
  
  // 停止计时器
  stopTimer() {
    if (this.timerId !== -1) {
      clearInterval(this.timerId);
      this.timerId = -1; // 重置ID
    }
  }
  
  // 页面销毁时清理
  aboutToDisappear() {
    this.stopTimer(); // ✅ 确保定时器被销毁
  }
}

2.3 关键要点

复制代码
┌─────────────────────────────────────┐
│          定时器销毁规范              │
├─────────────────────────────────────┤
│  1. 使用timerId追踪定时器            │
│  2. 销毁后重置timerId为-1            │
│  3. 在aboutToDisappear中调用销毁     │
│  4. 避免重复启动定时器               │
└─────────────────────────────────────┘

三、不可变数组操作

3.1 问题分析

【图2:可变vs不可变操作】

复制代码
可变操作(❌ 不推荐):
┌─────────────────────────────────────┐
│  this.todoList.push(todo)           │
│  this.todoList[index] = todo        │
│  item.completed = !item.completed   │
└─────────────────────────────────────┘
         ↓
  直接修改原数组/对象
         ↓
  ❌ UI可能不刷新

不可变操作(✅ 推荐):
┌─────────────────────────────────────┐
│  this.todoList = [...this.todoList, todo]  │
│  this.todoList = this.todoList.map(...)    │
│  this.todoList = this.todoList.filter(...) │
└─────────────────────────────────────┘
         ↓
  创建新数组/对象
         ↓
  ✅ 触发UI刷新

3.2 优化前后对比

添加待办
typescript 复制代码
// ❌ 优化前:直接push
async addTodo(text: string): Promise<TodoItem> {
  const todo = createTodoItem(text);
  this.todoList.push(todo); // 直接修改原数组
  return todo;
}

// ✅ 优化后:创建新数组
async addTodo(text: string): Promise<TodoItem> {
  const todo = createTodoItem(text);
  this.todoList = [...this.todoList, todo]; // 创建新数组
  return todo;
}
更新待办
typescript 复制代码
// ❌ 优化前:直接修改索引
async updateTodo(todo: TodoItem): Promise<void> {
  const index = this.todoList.findIndex(item => item.id === todo.id);
  if (index !== -1) {
    this.todoList[index] = todo; // 直接修改
  }
}

// ✅ 优化后:使用map创建新数组
async updateTodo(todo: TodoItem): Promise<void> {
  this.todoList = this.todoList.map(item => 
    item.id === todo.id ? todo : item
  );
}
切换完成状态
typescript 复制代码
// ❌ 优化前:直接修改对象属性
async toggleTodoComplete(todoId: number): Promise<void> {
  const todo = this.todoList.find(item => item.id === todoId);
  if (todo) {
    todo.completed = !todo.completed; // 直接修改
  }
}

// ✅ 优化后:创建新对象
async toggleTodoComplete(todoId: number): Promise<void> {
  this.todoList = this.todoList.map(item => {
    if (item.id === todoId) {
      // 创建新对象
      const newItem: TodoItem = {
        id: item.id,
        text: item.text,
        completed: !item.completed,
        pomodoroCount: item.pomodoroCount,
        createdAt: item.createdAt
      };
      return newItem;
    }
    return item;
  });
}

3.3 不可变操作方法总结

操作 可变方法 不可变方法
添加 arr.push(item) arr = [...arr, item]
删除 arr.splice(i, 1) arr = arr.filter(...)
更新 arr[i] = item arr = arr.map(...)
修改属性 obj.prop = val 创建新对象

四、性能监控工具

4.1 PerformanceUtil实现

typescript 复制代码
import hilog from '@ohos.hilog';

export class PerformanceUtil {
  private static instance: PerformanceUtil | null = null;
  private timers: Map<string, number> = new Map();
  
  // 获取单例
  public static getInstance(): PerformanceUtil {
    if (!PerformanceUtil.instance) {
      PerformanceUtil.instance = new PerformanceUtil();
    }
    return PerformanceUtil.instance;
  }
  
  // 开始计时
  public startTimer(key: string): void {
    this.timers.set(key, Date.now());
  }
  
  // 结束计时
  public endTimer(key: string): number {
    const startTime = this.timers.get(key);
    if (startTime) {
      const duration = Date.now() - startTime;
      this.timers.delete(key);
      hilog.info(0x0000, 'Performance', `[${key}] 耗时: ${duration}ms`);
      return duration;
    }
    return 0;
  }
}

4.2 在业务代码中使用

typescript 复制代码
import { PerformanceUtil } from '../utils/PerformanceUtil';

export class TodoViewModel {
  private performanceUtil: PerformanceUtil = PerformanceUtil.getInstance();
  
  async addTodo(text: string): Promise<TodoItem> {
    this.performanceUtil.startTimer('addTodo');
    
    // 业务逻辑...
    this.todoList = [...this.todoList, todo];
    
    this.performanceUtil.endTimer('addTodo');
    return todo;
  }
}

五、最佳实践总结

5.1 定时器管理规范

【图3:定时器管理清单】

复制代码
┌─────────────────────────────────────┐
│          ✅ 定时器管理规范           │
├─────────────────────────────────────┤
│  □ 使用成员变量追踪timerId           │
│  □ 销毁后重置timerId                 │
│  □ 在aboutToDisappear中清理          │
│  □ 避免重复启动                      │
│  □ 使用性能监控记录耗时              │
└─────────────────────────────────────┘

5.2 数组操作规范

【图4:数组操作规范】

复制代码
┌─────────────────────────────────────┐
│          ✅ 数组操作规范             │
├─────────────────────────────────────┤
│  □ 添加:使用展开运算符 [...arr, item] │
│  □ 删除:使用filter创建新数组         │
│  □ 更新:使用map创建新数组            │
│  □ 修改属性:创建新对象               │
│  □ 避免直接修改原数组/对象            │
└─────────────────────────────────────┘

六、总结

本文介绍了HarmonyOS应用性能优化的两个关键实践:

  1. 定时器销毁:确保页面退出时清理定时器,避免内存泄漏
  2. 不可变数组操作:使用创建新数组的方式触发UI刷新

这些优化可以显著提升应用的稳定性和用户体验。


相关推荐
李昊哲小课1 天前
Spring Boot 4 旅游主题实战教程 阶段四:缓存与底层进阶
spring boot·redis·缓存·性能优化·log4j·旅游·性能
人丰1 天前
血泪复盘:一次由 HttpContext.Current 引发的 CPU 100% 惨案
性能优化·.net
晓晓_za8986681 天前
GEO 搜索源码白帽合规改造:适配各大 AI 信源收录规则
java·开发语言·人工智能·性能优化·开源
yunwei371 天前
CPU 噪声会拖慢 GPU 推理吗:用 eBPF 定量测量调度器与 IRQ 影响
linux·人工智能·性能优化
kyle~1 天前
x86 汇编LOCK前缀 --- 硬件架构向软件提供的核心同步原语
汇编·c++·性能优化·硬件架构·实时系统
devilnumber2 天前
MySQL 性能优化・诗意化记忆
数据库·mysql·性能优化
ly76892 天前
Web 性能优化实战:从 Core Web Vitals 到工程化性能治理
前端·性能优化
李昊哲小课2 天前
SpringBoot4 云端咖啡站 阶段四:安全、文件与性能
spring boot·安全·性能优化·文件·性能
小小杨树2 天前
【C++】学习:双缓冲视频流水线深解析
c++·性能优化·音视频开发
k4m7v2pz2 天前
Godot 4 仿 agar.io 卡顿优化:用空间网格把 30 万次碰撞检测降到几千次
性能优化·godot·游戏开发·碰撞检测·空间网格