鸿蒙应用开发—功耗优化(后台任务篇)

功耗优化在鸿蒙移动应用开发中占据着至关重要的地位,它直接关系到用户体验、设备续航以及应用在后台的运行效率。鸿蒙系统作为华为推出的全场景分布式操作系统,在功耗管理方面提供了丰富的特性和API支持。

在开发过程中,我们发现功耗热点主要集中在以下几方面:

  • 后台任务:不合理的使用后台任务会导致设备无法进入休眠状态
  • 网络请求:频繁的网络活动尤其是移动数据使用会显著增加功耗
  • 定位服务:持续高精度的GPS定位会快速耗尽电池
  • 屏幕与图形:不合理的UI刷新策略和动画效果会增加GPU负担
  • 传感器使用:未及时释放的传感器监听会持续消耗电量

那么针对以上几点,一起来详细探讨下如何进行性能优化叭:

一、后台任务(长时任务和短时任务)

1.短时任务的合理使用

短时任务(Short-time Task)适用于应用退至后台后需要临时完成一些耗时较短的操作,如小文件下载、缓存处理或信息发送等。

以下是一个申请短时任务执行计算的demo

typescript 复制代码
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';
import { util } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';

const totalTimes: number = 50000000; // 循环次数
const calculateResult: string = 'Total time costed = %s ms.'; // 文本格式

@Entry
@Component
struct Index {
  @State message: string = 'Click button to calculate.';
  private requestId: number = 0;

  // 申请短时任务
  requestSuspendDelay() {
    try {
      let delayInfo = backgroundTaskManager.requestSuspendDelay('compute', () => {
        console.info('Request suspension delay will time out.');
        // 任务即将超时,取消短时任务
        this.cancelSuspendDelay();
      })
      this.requestId = delayInfo.requestId;
    } catch (error) {
      console.error(`requestSuspendDelay failed. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
    }
  }

  // 取消短时任务
  cancelSuspendDelay() {
    backgroundTaskManager.cancelSuspendDelay(this.requestId);
    console.info('Request suspension delay cancel.');
  }

  // 计算任务
  computeTask(times: number): number {
    let start: number = new Date().getTime();
    let a: number = 1;
    let b: number = 1;
    let c: number = 1;
    for (let i: number = 0; i < times; i++) {
      a = a * Math.random() + b * Math.random() + c * Math.random();
      b = a * Math.random() + b * Math.random() + c * Math.random();
      c = a * Math.random() + b * Math.random() + c * Math.random();
    }
    let end: number = new Date().getTime();
    return end - start;
  }

  // 点击回调
  clickCallback = () => {
    this.requestSuspendDelay();
    hiTraceMeter.startTrace('computeTask', 0); // 开启性能打点
    let timeCost = this.computeTask(totalTimes);
    this.message = util.format(calculateResult, timeCost.toString());
    hiTraceMeter.finishTrace('computeTask', 0); // 结束性能打点
    this.cancelSuspendDelay();
  }

  build() {
    Column() {
      Row(){
        Text(this.message)
      }
      Row() {
        Button('开始计算')
          .onClick(this.clickCallback)
      }
      .width('100%')
      .justifyContent(FlexAlign.Center)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

从性能分析数据来看,短时任务执行阶段应用主线程的平均CPU占用率为12.6%,最高达到40.0%;而任务取消后未被挂起阶段的平均CPU占用率降至2.2%,最高28.6%。这表明短时任务确实会显著增加系统资源消耗,因此总结出以下经验:

  • 最小化任务时长:尽可能缩短短时任务的执行时间,避免长时间占用系统资源
  • 避免并发任务:同时运行多个短时任务会导致CPU负载过高,可能引起前台应用卡顿
  • 及时释放资源:任务完成后应立即取消短时任务申请,减少不必要的能耗
  • 异常处理:添加适当的错误处理逻辑,确保任务异常时也能正确释放资源

2.长时任务的适用场景与优化

长时任务(Long-time Task)适用于需要在后台持续运行用户可感知的功能,如音乐播放、导航、录音等。与短时任务不同,长时任务允许应用在后台长时间运行,但需要声明具体的任务类型,并且系统会进行严格的权限校验。

长时任务使用场景

根据官方文档给出的长时任务使用场景,写了一个音视频播放长时任务的demo:

typescript 复制代码
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common, wantAgent } from '@kit.AbilityKit';

@Entry
@Component
struct MusicPlayer {
  private longTaskId: number = 0;

  // 申请音视频播放长时任务
  requestContinuousTask() {
    try {
      backgroundTaskManager.startBackgroundRunning(getContext(),
        backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,{
          // 点击通知后,将要执行的动作列表
          // 添加需要被拉起应用的bundleName和abilityName
          wants: [
            {
              bundleName: (getContext() as common.UIAbilityContext).abilityInfo.bundleName,
              abilityName: "EntryAbility"
            }
          ],
          // 指定点击通知栏消息后的动作是拉起ability
          actionType: wantAgent.OperationType.START_ABILITY,
          // 使用者自定义的一个私有值
          requestCode: 0,
          // 点击通知后,动作执行属性
          actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG],
        }).then(() => {
        console.info('Audio playback long-term task requested');
        this.startMusicPlayback();
      }).catch((err: BusinessError) => {
        console.error(`Failed to request audio playback task. Code: ${err.code}, message: ${err.message}`);
      });
    } catch (error) {
      console.error(`Exception when requesting audio playback task. Code: ${(error as BusinessError).code}, message: ${(error as BusinessError).message}`);
    }
  }

  // 取消长时任务
  stopContinuousTask() {
    try {
      backgroundTaskManager.stopBackgroundRunning(getContext()).then(() => {
        console.info('Long-term task stopped');
        this.stopMusicPlayback();
      }).catch((err: BusinessError) => {
        console.error(`取消长时任务失败 Code: ${err.code}, message: ${err.message}`);
      });
    } catch (error) {
      console.error(`取消长时任务出现异常 Code: ${(error as BusinessError).code}, message: ${(error as BusinessError).message}`);
    }
  }

  // 模拟音乐播放开始
  startMusicPlayback() {
    console.info('音乐后台播放');
    // 实际音乐播放逻辑...
  }

  // 模拟音乐播放停止
  stopMusicPlayback() {
    console.info('音乐后台播放停止');
    // 实际音乐停止逻辑...
  }

  build() {
    Column() {
      Button('开始音乐后台播放')
        .onClick(() => this.requestContinuousTask())
      Button('停止音乐后台播放')
        .onClick(() => this.stopContinuousTask())
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

对于长时任务,我总结出以下优化点:

  • 按需申请:仅在确实需要时才申请长时任务,任务完成后立即释放
  • 类型匹配:准确声明任务类型,避免滥用通用类型
  • 资源释放:任务停止时释放所有相关资源,包括媒体播放器、定位服务等
  • 适配系统限制:不同任务类型可能有特殊要求,如音视频播放必须使用媒体会话服务
  • 用户感知:对于录音等涉及隐私的任务,必须提供明确的用户提示和授权机制

针对后台任务优化还有其他各个方面,如线程池与任务调度、延迟任务等,欢迎各位小伙伴一起讨论

相关推荐
HarmonyOS_SDK1 小时前
支付宝携手HarmonyOS SDK实况窗,开启便捷停车生活
harmonyos
二蛋和他的大花1 小时前
鸿蒙运动项目开发:项目运行环境切换器
harmonyos
深海的鲸同学luvi2 小时前
【HarmonyOS 5】应用更新功能详解
harmonyos
半路下车10 小时前
【Harmony OS 5】UNIapp在教育类应用中的实践与ArkTS实现
深度学习·uni-app·harmonyos
libo_202510 小时前
基于HarmonyOS 5的CryEngine跨平台游戏开发实践指南
harmonyos
libo_202510 小时前
HarmonyOS 5分布式能力在CryEngine多设备联动中的应用
harmonyos
zhanshuo11 小时前
鸿蒙APP布局总出问题?看看你踩了这5个坑没
harmonyos
zhanshuo11 小时前
鸿蒙视频播放失败全解:格式、路径、权限一网打尽!
harmonyos
万少12 小时前
95 后不靠大厂,凭 HarmonyOS 开发小众 APP 竟月入 7 万,他是怎么做到的
前端·harmonyos