【OpenHarmony/HarmonyOs 】CheckMe 性能优化中心实践:资源健康评分、一键整理与本地缓存清理

本文基于 CheckMe 项目的性能优化中心展开,聚焦资源健康评分、一键整理、本地缓存清理和优化建议生成,适合用于讲解 HarmonyOS 工具类应用的状态评估与可执行操作设计。

HarmonyOS 工具类应用如果只展示设备状态,用户看完以后还会问一句:那我现在该怎么办?

CheckMe 的性能优化中心就是为了解决这个问题:它不只是展示 CPU、内存、存储、电池这些状态,而是把它们整理成一个可理解的健康评分,并给出可执行建议。

这篇文章重点拆解:

  • 性能健康评分如何设计
  • CPU / 内存 / 存储 / 电池如何形成体检项
  • 一键优化为什么只清理本应用可控临时数据
  • Preferences 如何记录优化结果
  • 工具类 App 如何避免“假优化” 🚀

一、为什么需要性能优化中心

很多设备状态 App 会展示大量数据:

  • CPU 80%
  • 内存剩余 1.2GB
  • 存储使用率 78%
  • 电池温度 41℃

但普通用户并不一定知道这些数字意味着什么。

因此,性能优化中心要做的不是再堆一组数字,而是把数据翻译成结论:

  • 当前状态是否健康
  • 哪个指标最需要关注
  • 是否建议继续跑性能测试
  • 是否存在可清理临时文件
  • 下一步应该进入哪个工具页

CheckMe 的实现思路是:

设备状态数据
  -> 体检项 CheckItem
  -> 健康评分 Score
  -> 优化建议 Suggestion
  -> 一键整理 Action

这比单纯展示数据更接近真实工具产品。


二、页面结构:从 Summary 到 Suggestions

性能优化页 PerformanceOptimizer.ets 的状态非常清晰:

@State isLoading: boolean = true;
@State isOptimizing: boolean = false;
@State snapshot: PerformanceOptimizationSnapshot | null = null;
@State actionMessage: string = '';

private optimizationService: PerformanceOptimizationService =
  PerformanceOptimizationService.getInstance();

页面主要分成几个区域:

  • SummaryCard:健康评分和状态摘要
  • OptimizeActionCard:一键优化入口
  • HealthChecksCard:CPU、内存、存储、电池体检项
  • SuggestionsCard:优化建议
  • ShortcutsCard:跳转到相关工具

构建页面时:

Scroll() {
  Column({ space: 14 }) {
    this.SummaryCard(this.snapshot as PerformanceOptimizationSnapshot);
    this.OptimizeActionCard(this.snapshot as PerformanceOptimizationSnapshot);
    this.HealthChecksCard((this.snapshot as PerformanceOptimizationSnapshot).checkItems);
    this.SuggestionsCard((this.snapshot as PerformanceOptimizationSnapshot).suggestions);
    this.ShortcutsCard();
  }
  .width('100%')
  .padding(16)
}

这类页面结构很适合 CSDN 项目文章,因为它体现了“数据 -> 结论 -> 操作”的完整闭环。


三、Snapshot:优化中心的数据快照

优化中心没有直接在页面里计算评分,而是通过服务层获取快照:

private async loadSnapshot(): Promise<void> {
  this.isLoading = true;
  try {
    const ctx: common.UIAbilityContext =
      getContext(this) as common.UIAbilityContext;
    this.snapshot = await this.optimizationService.getSnapshot(ctx);
  } catch (_e) {
    promptAction.showToast({ message: '读取优化状态失败' });
    this.snapshot = null;
  }
  this.isLoading = false;
}

这样做有两个好处:

  1. 页面只负责展示,不负责复杂计算。
  2. 评分、建议、清理逻辑可以独立测试和维护。

性能优化中心的核心不是 UI,而是 PerformanceOptimizationSnapshot

它应该包含:

  • 总分
  • 状态标题
  • 状态摘要
  • 缓存大小
  • 上次优化记录
  • 体检项列表
  • 优化建议列表

这就是页面展示的统一数据源。


四、体检项:CPU、内存、存储、电池分开判断

项目把每个指标拆成独立函数。

例如 CPU:

function buildCpuCheck(cpuUsagePercent: number): OptimizationCheckItem {
  let level: OptimizationStatusLevel = 'good';
  let summary: string = '当前负载平稳';

  if (cpuUsagePercent >= 80) {
    level = 'critical';
    summary = '当前负载较高,建议暂停连续重负载测试';
  } else if (cpuUsagePercent >= 55) {
    level = 'warning';
    summary = '当前负载偏高,建议稍后再进行连续测试';
  }

  return {
    id: 'cpu',
    title: 'CPU 状态',
    level: level,
    summary: summary,
    valueText: Math.round(cpuUsagePercent).toString() + '%'
  };
}

这种写法比在页面中写一堆 if 更清晰。

每个体检项都有统一结构:

interface OptimizationCheckItem {
  id: string;
  title: string;
  level: OptimizationStatusLevel;
  summary: string;
  valueText: string;
}

后续页面只需要根据 level 决定颜色和展示样式。


五、内存判断:不要只看百分比

内存体检既看剩余容量,也看比例:

function buildMemoryCheck(memory: MemoryInfo): OptimizationCheckItem {
  const availableMb: number = memory.availableMem;
  const ratio: number = memory.totalMem > 0
    ? availableMb / memory.totalMem
    : 0;

  let level: OptimizationStatusLevel = 'good';
  let summary: string = '可用内存充足';

  if (availableMb < 1024 || ratio < 0.10) {
    level = 'critical';
    summary = '可用内存较低,建议结束连续重负载操作';
  } else if (availableMb < 2048 || ratio < 0.25) {
    level = 'warning';
    summary = '可用内存偏低,建议减少并发任务';
  }

  return {
    id: 'memory',
    title: '内存状态',
    level: level,
    summary: summary,
    valueText: (availableMb / 1024).toFixed(1) + ' GB 可用'
  };
}

这里有一个很重要的设计点:不要只看百分比。

比如:

  • 8GB 设备剩余 1GB,体验可能已经紧张
  • 16GB 设备剩余 2GB,仍然要结合场景判断

所以项目同时考虑绝对值和比例,更接近真实使用体验。


六、存储判断:高占用时给出明确建议

存储体检逻辑:

function buildStorageCheck(storage: StorageInfo | null): OptimizationCheckItem {
  if (storage === null || storage.usagePercent === undefined) {
    return {
      id: 'storage',
      title: '存储状态',
      level: 'unavailable',
      summary: '暂未获取到存储数据',
      valueText: '--'
    };
  }

  const usagePercent: number = storage.usagePercent;
  let level: OptimizationStatusLevel = 'good';
  let summary: string = '存储空间充足';

  if (usagePercent >= 85) {
    level = 'critical';
    summary = '存储占用过高,建议优先释放空间';
  } else if (usagePercent >= 70) {
    level = 'warning';
    summary = '存储空间开始紧张,建议检查大文件';
  }

  return {
    id: 'storage',
    title: '存储状态',
    level: level,
    summary: summary,
    valueText: usagePercent.toFixed(1) + '%'
  };
}

存储建议不能太夸张。第三方应用不应该宣称自己能清理系统垃圾,它只能清理自己可控范围内的文件。

这也是 CheckMe 设计上比较克制的一点。


七、一键优化:只处理本应用临时文件

优化服务会扫描应用临时目录:

private async collectCleanupCandidates(
  ctx: common.UIAbilityContext
): Promise<CleanupCandidate[]> {
  const candidates: CleanupCandidate[] = [];
  let fileNames: string[] = [];

  try {
    fileNames = fileIO.listFileSync(ctx.tempDir);
  } catch (_e) {
    return candidates;
  }

  for (let i = 0; i < fileNames.length; i++) {
    const fullPath: string = ctx.tempDir + '/' + fileNames[i];
    if (!isManagedOptimizationTempFile(fullPath)) {
      continue;
    }
    const stat = fileIO.statSync(fullPath);
    if (!stat.isDirectory()) {
      candidates.push({
        path: fullPath,
        sizeBytes: Number(stat.size)
      });
    }
  }

  return candidates;
}

只允许清理受管理的临时文件:

export function isManagedOptimizationTempFile(path: string): boolean {
  const fileName: string = getFileName(path);
  return fileName === 'bench_io_tmp.bin' ||
    fileName.startsWith('bench_') ||
    fileName.startsWith('optimizer_');
}

这个设计非常适合写进文章:

一键优化不是越大越好,而是越可信越好。

项目只清理自己创建、自己识别、自己负责的文件,避免误删用户数据或系统文件。


八、执行优化并持久化结果

执行优化时:

public async runOptimization(ctx: common.UIAbilityContext): Promise<{
  cleanup: OptimizationCleanupResult;
  snapshot: PerformanceOptimizationSnapshot;
}> {
  const pref: dataPreferences.Preferences = await this.getPreferences(ctx);
  const cleanupCandidates: CleanupCandidate[] =
    await this.collectCleanupCandidates(ctx);

  const cleanup: OptimizationCleanupResult =
    summarizeCleanupCandidates(cleanupCandidates);
  cleanup.executedAt = Date.now();

  for (let i = 0; i < cleanupCandidates.length; i++) {
    try {
      fileIO.unlinkSync(cleanupCandidates[i].path);
    } catch (_e) {
      cleanup.partialFailure = true;
    }
  }

  await pref.put(KEY_LAST_OPTIMIZED_AT, cleanup.executedAt);
  await pref.put(KEY_LAST_RELEASED_BYTES, cleanup.releasedBytes);
  await pref.flush();

  const snapshot: PerformanceOptimizationSnapshot =
    await this.getSnapshot(ctx);

  return {
    cleanup: cleanup,
    snapshot: snapshot
  };
}

这里做了三件事:

  • 删除可控临时文件
  • 记录优化时间和释放空间
  • 重新生成优化快照

用户点击按钮后,页面拿到新快照,就能立即刷新状态。


九、优化建议:从指标跳转到工具

建议不是空泛文字,而是可以带行动入口:

suggestions.push({
  id: 'storage_pressure',
  priority: 100,
  title: '优先处理存储压力',
  description: '当前存储使用率较高,先释放空间再继续连续测试会更稳妥。',
  actionLabel: '查看存储分析',
  actionRoute: 'pages/StorageAnalysis'
});

页面中展示时:

if (item.actionLabel !== undefined && item.actionRoute !== undefined) {
  Text((item.actionLabel as string) + ' >')
    .fontSize(11)
    .fontColor('#3B82F6')
    .onClick(() => {
      router.pushUrl({ url: item.actionRoute as string });
    })
}

这让优化中心变成一个“问题分发入口”:

  • 存储压力 -> 存储分析
  • 内存压力 -> 设备诊断
  • 存储未校准 -> 关于页

用户不是看完建议就结束,而是可以继续处理问题。


十、文章小结

CheckMe 的性能优化中心不是系统清理器,而是一个本地可信的资源健康面板:

  • 用体检项表达 CPU、内存、存储、电池状态
  • 用评分降低理解成本
  • 用建议告诉用户下一步做什么
  • 用本应用临时目录实现安全清理
  • 用 Preferences 记录上次优化结果
  • 用工具入口串联存储分析、设备诊断、关于页

最后一句总结:真正可靠的一键优化,不是承诺清理整个系统,而是在应用权限边界内做真实、可解释、可回滚的整理。 🧹


参考资料

img

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐