Harmony os——延迟任务(WorkScheduler,ArkTS)速记 & 思维导图版

100 阅读4分钟

延迟任务(WorkScheduler,ArkTS)速记 & 思维导图版

一句话: 不追求“马上执行”,只要“有条件就帮我跑一下”的后台任务 → 用延迟任务(WorkScheduler + WorkSchedulerExtensionAbility)。


1. 延迟任务是干嘛的?

典型场景(实时性不高):

  • 有网时,偶尔主动去拉一下邮件 / 消息
  • 设备空闲 + Wi-Fi 时,把日志/数据同步到服务器
  • 充电 + 空闲时,做一些清理/压缩/上报类任务

特点:

  • 应用可以退到后台,不用一直活着。

  • 由系统根据:

    • 任务条件:网络类型、充电状态、存储、电池、定时等
    • 系统状态:内存、功耗、温度、用户习惯等 统一决定啥时候拉起你的 WorkSchedulerExtensionAbility 来执行任务。

2. 运行原理(背后的流程)

  1. 你的应用通过 workScheduler.startWork(workInfo) 申请延迟任务

  2. WorkInfo 里配置任务触发条件:

    • networkType(WiFi/蜂窝…)
    • 后续可以配置:充电、存储、电量、定时等(在其他文档的 WorkInfo 字段)。
  3. 延迟任务管理模块统一决策什么时候调度:

    • 当条件满足 → 拉起一个 Extension 进程,创建 WorkSchedulerExtensionAbility 实例。
  4. 回调:

    • onWorkStart(workInfo):任务真正开始,写你的业务逻辑。
    • onWorkStop(workInfo):任务结束(超时 2 分钟,或你主动 stop,都会回调这里)。

系统给 WorkSchedulerExtensionAbility 最多 2 分钟活动周期,超时不收工 → 进程会被系统干掉。


3. 约束与限制(必考点)

3.1 数量限制

  • 一个应用 同一时刻最多 10 个延迟任务

3.2 执行频率限制(跟“应用活跃程度”强相关)

系统会把应用分组,不同分组限制延迟任务的最小执行间隔

应用活跃分组延迟任务最小间隔
活跃分组≥ 2 小时
经常使用分组≥ 4 小时
常用分组≥ 24 小时
极少使用分组≥ 48 小时
受限使用分组禁止调度
从未使用分组禁止调度

所以:延迟任务不适合高频任务(比如每 5 分钟一次),会被系统限制。

3.3 超时 & 调度延迟

  • 单次回调:

    • onWorkStart 对应的一次任务最多 运行 2 分钟
    • 超时还不取消 → 系统终止对应 Extension 进程
  • 调度可能被延后:

    • 如果系统内存、温度、功耗紧张 → 可能会延迟你的任务执行时间。

3.4 WorkSchedulerExtensionAbility 里的禁止调用接口

为了控制能力,在 WorkSchedulerExtensionAbility 中限制以下模块调用

  • @ohos.resourceschedule.backgroundTaskManager / @ohos.backgroundTaskManager(后台任务管理)
  • @ohos.multimedia.camera(相机)
  • @ohos.multimedia.audio(音频)
  • @ohos.multimedia.media(媒体服务)

意思:延迟任务更适合 纯计算 / 网络 / 文件 这类,不适合复杂的多媒体场景。


4. 关键 API 速查表

模块:import { workScheduler } from '@kit.BackgroundTasksKit';

4.1 管理任务(发起/取消)

  • 申请延迟任务

     workScheduler.startWork(workInfo: WorkInfo): void;
    
  • 取消延迟任务

     workScheduler.stopWork(workInfo: WorkInfo, needCancel?: boolean): void;
    
    • needCancel 省略时,默认取消该 Work。
    • 对 repeat 任务,是否算彻底取消由 needCancel 决定。

4.2 查询任务

  • 获取某个任务状态

     workScheduler.getWorkStatus(workId: number): Promise<WorkInfo>;
     // 或 Callback 版本
    
  • 获取当前所有延迟任务

     workScheduler.obtainAllWorks(): Promise<Array<WorkInfo>>;
    
  • 停止并清空所有任务

     workScheduler.stopAndClearWorks(): void;
    

4.3 判断上次是否超时(只针对 RepeatWork)

  • 返回上一次执行是否超时:

     workScheduler.isLastWorkTimeOut(workId: number): Promise<boolean>;
    

5. 开发步骤拆解

延迟任务 = 两部分一起配合

  1. 扩展能力:实现 WorkSchedulerExtensionAbility(回调用来真正执行任务)
  2. 调度侧:在普通 UIAbility 里,用 workScheduler 添加/删除任务

5.1 实现 WorkSchedulerExtensionAbility(“任务执行者”)

  1. 创建目录与文件

    • entry/src/main/ets 下新建目录:WorkSchedulerExtension/
    • 在该目录下新建 WorkSchedulerExtension.ets
  2. 导入模块并继承

     import { WorkSchedulerExtensionAbility, workScheduler } from '@kit.BackgroundTasksKit';
     ​
     export default class MyWorkSchedulerExtensionAbility extends WorkSchedulerExtensionAbility {
       // 延迟任务开始
       onWorkStart(workInfo: workScheduler.WorkInfo) {
         console.info(`onWorkStart, workInfo = ${JSON.stringify(workInfo)}`);
         // 在这里执行你的任务逻辑(网络请求、同步数据等)
         // 如有自定义参数,可从 workInfo.parameters 里解析
         // console.info(`key1: ${JSON.parse(workInfo.parameters?.toString()).key1}`);
       }
     ​
       // 延迟任务结束:
       // - 超过 2 分钟
       // - 或应用通过 stopWork 主动取消
       onWorkStop(workInfo: workScheduler.WorkInfo) {
         console.info(`onWorkStop, workInfo = ${JSON.stringify(workInfo)}`);
         // 收尾逻辑写这里
       }
     }
    
  3. 在 module.json5 注册 ExtensionAbility

     {
       "module": {
         "extensionAbilities": [
           {
             "name": "MyWorkSchedulerExtensionAbility",
             "srcEntry": "./ets/WorkSchedulerExtension/WorkSchedulerExtension.ets",
             "type": "workScheduler"
           }
         ]
       }
     }
    

5.2 实现延迟任务调度(“任务调度者”)

在 UIAbility/页面中编写逻辑,使用 workScheduler 添加/取消任务。

  1. 导入模块

     import { workScheduler } from '@kit.BackgroundTasksKit';
     import { BusinessError } from '@kit.BasicServicesKit';
    
  2. 申请延迟任务:

     const workInfo: workScheduler.WorkInfo = {
       workId: 1, // 任务唯一ID
       networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI, // 只在 WiFi 下触发
       bundleName: 'com.example.application',                    // 你的应用包名
       abilityName: 'MyWorkSchedulerExtensionAbility'            // 扩展能力名(上面注册的 name)
       // 其他条件(充电、电量、存储、重复执行等)可在 WorkInfo 里额外配置
     };
     ​
     try {
       workScheduler.startWork(workInfo);
       console.info('startWork success');
     } catch (error) {
       console.error(`startWork failed. code: ${(error as BusinessError).code}, msg: ${(error as BusinessError).message}`);
     }
    
  3. 取消延迟任务:

     const workInfo: workScheduler.WorkInfo = {
       workId: 1,
       networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
       bundleName: 'com.example.application',
       abilityName: 'MyWorkSchedulerExtensionAbility'
     };
     ​
     try {
       workScheduler.stopWork(workInfo);
       console.info('stopWork success');
     } catch (error) {
       console.error(`stopWork failed. code: ${(error as BusinessError).code}, msg: ${(error as BusinessError).message}`);
     }
    
  4. 测试回调是否生效(调试技巧)

    • 正常逻辑要等“条件满足 + 系统调度”才会触发 onWorkStart / onWorkStop

    • 为了快速验证,可以用 hidumper 命令手动触发

       hidumper -s 1904 -a '-t com.example.application MyWorkSchedulerExtensionAbility'
      

6. 延迟任务 vs 短时任务 vs 长时任务(小总表)

对比点短时任务(requestSuspendDelay)长时任务(startBackgroundRunning)延迟任务(WorkScheduler)
典型场景退后台前抢一点时间做收尾(保存状态等)后台持续播放/导航/通话等用户可感知业务不急的周期性任务:同步、拉取邮件、清理日志等
是否立刻跑立刻执行当前逻辑立刻执行,退后台仍保持运行不一定立刻,等待系统判断条件满足后再执行
持续时间单次几分钟,配额每日约 10 分钟可长时间运行,只要业务真实且类型匹配单次回调最多 2 分钟
系统调度主要按“挂起前缓冲”来管控根据业务类型 + AVSession/后台模式严格校验按活跃度分组 + 系统状态决定调度频率和时间点
实现方式backgroundTaskManager.requestSuspendDelaybackgroundTaskManager.startBackgroundRunning + WantAgentworkScheduler.startWork + WorkSchedulerExtensionAbility