延迟任务(WorkScheduler,ArkTS)速记 & 思维导图版
一句话: 不追求“马上执行”,只要“有条件就帮我跑一下”的后台任务 → 用延迟任务(WorkScheduler + WorkSchedulerExtensionAbility)。
1. 延迟任务是干嘛的?
典型场景(实时性不高):
- 有网时,偶尔主动去拉一下邮件 / 消息
- 设备空闲 + Wi-Fi 时,把日志/数据同步到服务器
- 充电 + 空闲时,做一些清理/压缩/上报类任务
特点:
-
应用可以退到后台,不用一直活着。
-
由系统根据:
- 任务条件:网络类型、充电状态、存储、电池、定时等
- 系统状态:内存、功耗、温度、用户习惯等 统一决定啥时候拉起你的 WorkSchedulerExtensionAbility 来执行任务。
2. 运行原理(背后的流程)
-
你的应用通过
workScheduler.startWork(workInfo)申请延迟任务。 -
WorkInfo 里配置任务触发条件:
networkType(WiFi/蜂窝…)- 后续可以配置:充电、存储、电量、定时等(在其他文档的 WorkInfo 字段)。
-
延迟任务管理模块统一决策什么时候调度:
- 当条件满足 → 拉起一个 Extension 进程,创建
WorkSchedulerExtensionAbility实例。
- 当条件满足 → 拉起一个 Extension 进程,创建
-
回调:
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. 开发步骤拆解
延迟任务 = 两部分一起配合:
- 扩展能力:实现
WorkSchedulerExtensionAbility(回调用来真正执行任务) - 调度侧:在普通 UIAbility 里,用
workScheduler添加/删除任务
5.1 实现 WorkSchedulerExtensionAbility(“任务执行者”)
-
创建目录与文件
- 在
entry/src/main/ets下新建目录:WorkSchedulerExtension/ - 在该目录下新建
WorkSchedulerExtension.ets
- 在
-
导入模块并继承
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)}`); // 收尾逻辑写这里 } } -
在 module.json5 注册 ExtensionAbility
{ "module": { "extensionAbilities": [ { "name": "MyWorkSchedulerExtensionAbility", "srcEntry": "./ets/WorkSchedulerExtension/WorkSchedulerExtension.ets", "type": "workScheduler" } ] } }
5.2 实现延迟任务调度(“任务调度者”)
在 UIAbility/页面中编写逻辑,使用 workScheduler 添加/取消任务。
-
导入模块
import { workScheduler } from '@kit.BackgroundTasksKit'; import { BusinessError } from '@kit.BasicServicesKit'; -
申请延迟任务:
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}`); } -
取消延迟任务:
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}`); } -
测试回调是否生效(调试技巧)
-
正常逻辑要等“条件满足 + 系统调度”才会触发
onWorkStart / onWorkStop。 -
为了快速验证,可以用 hidumper 命令手动触发:
hidumper -s 1904 -a '-t com.example.application MyWorkSchedulerExtensionAbility'
-
6. 延迟任务 vs 短时任务 vs 长时任务(小总表)
| 对比点 | 短时任务(requestSuspendDelay) | 长时任务(startBackgroundRunning) | 延迟任务(WorkScheduler) |
|---|---|---|---|
| 典型场景 | 退后台前抢一点时间做收尾(保存状态等) | 后台持续播放/导航/通话等用户可感知业务 | 不急的周期性任务:同步、拉取邮件、清理日志等 |
| 是否立刻跑 | 立刻执行当前逻辑 | 立刻执行,退后台仍保持运行 | 不一定立刻,等待系统判断条件满足后再执行 |
| 持续时间 | 单次几分钟,配额每日约 10 分钟 | 可长时间运行,只要业务真实且类型匹配 | 单次回调最多 2 分钟 |
| 系统调度 | 主要按“挂起前缓冲”来管控 | 根据业务类型 + AVSession/后台模式严格校验 | 按活跃度分组 + 系统状态决定调度频率和时间点 |
| 实现方式 | backgroundTaskManager.requestSuspendDelay | backgroundTaskManager.startBackgroundRunning + WantAgent | workScheduler.startWork + WorkSchedulerExtensionAbility |