Harmony os——短时任务(ArkTS)速记 & 开发小抄

86 阅读3分钟

短时任务(ArkTS)速记 & 开发小抄

一句话理解: 应用快要被挂起前,向系统“打个招呼”,再多要一点点后台运行时间,把收尾工作做完。


1. 为什么需要短时任务?

正常情况下:

  • 应用退到后台 → 一段时间后进程会被挂起 → 无法继续跑代码。

但有些场景需要:

  • 退后台前保存状态 / 发一条消息 / 同步一点数据,时间不长,但又不能被中途砍掉。 → 这时候就用 短时任务(suspend delay) ,让应用在后台还能「多活一会儿」。

典型用途:

  • 保存草稿、保存关卡进度
  • 发送关键埋点 / 日志 / 消息
  • 做一个很短的小收尾逻辑

2. 使用限制 & 配额规则

2.1 申请时机

不在这两个时机申请 = 必失败

  • 只能在:

    • 应用处于前台
    • 或者 onBackground 回调里 调用 requestSuspendDelay()

2.2 数量限制

  • 同一时刻,一个应用最多有 3 个短时任务 在跑。

2.3 配额机制(重点记忆)

  • 系统会给每个应用一个「短时任务额度」,由系统根据状态和用户习惯动态调整,大致规则:

    • 单日(24 小时)配额:默认 10 分钟
    • 单次最长:3 分钟
    • 低电量时单次:默认 1 分钟
  • 计时规则(只在后台计时、同一时间段不重复算):

    • 只有当应用在后台,短时任务才消耗配额。
    • 同一应用在同一时间段内有多个短时任务 → 只算一次时间(不叠加)。

图里的意思就是: 前台不计时,后台有短时任务就开始计,当 A 结束但 B 还在→ 继续计时。


2.4 超时 & 主动取消

  • 当短时任务快超时时:

    • 系统会回调你在 requestSuspendDelay 里传的 callback

    • 你应该在回调里:

      • 做一点简单的清理 / 标记
      • 然后调用 cancelSuspendDelay() 取消短时任务
  • 如果超时你还不取消:

    • 系统会对你的应用「下手」:

      • 进程挂起,严重时直接终止进程。
  • 强烈推荐: 业务自己结束时,也主动 cancelSuspendDelay,节省配额。


3. 相关 API 一览(backgroundTaskManager)

 import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
 import { BusinessError } from '@kit.BasicServicesKit';

3.1 申请短时任务

 function requestSuspendDelay() {
   let myReason = 'test requestSuspendDelay';   // 申请原因(日志可见)
 ​
   try {
     let delayInfo = backgroundTaskManager.requestSuspendDelay(myReason, () => {
       // ⬇️ 短时任务即将超时时会回调这里
       console.info('suspend delay task will timeout');
       try {
         backgroundTaskManager.cancelSuspendDelay(id);
       } catch (error) {
         console.error(`cancelSuspendDelay failed. code: ${(error as BusinessError).code}, message: ${(error as BusinessError).message}`);
       }
     });
 ​
     id = delayInfo.requestId;        // 本次短时任务 ID(后续查询 / 取消用)
     delayTime = delayInfo.actualDelayTime; // 实际给你的延长时间 ms
   } catch (error) {
     console.error(`requestSuspendDelay failed. code: ${(error as BusinessError).code}, message: ${(error as BusinessError).message}`);
   }
 }
  • 返回的 DelaySuspendInfo 里有:

    • requestId:短时任务编号
    • actualDelayTime:这次系统实际给了你多少时间(可能比上限少)

3.2 查询剩余时间

 async function getRemainingDelayTime() {
   backgroundTaskManager.getRemainingDelayTime(id)
     .then((res: number) => {
       console.info('Succeeded in getting remaining delay time.', res); // 单位 ms
       // 根据 res 判断要不要执行下一个小任务
     })
     .catch((err: BusinessError) => {
       console.error(`Failed to get remaining delay time. Code: ${err.code}, message: ${err.message}`);
     });
 }

用法建议: 比如你有两个小任务 A、B,做完 A 后看下剩余时间够不够做 B,不够就只做 A,避免被系统硬停。


3.3 取消短时任务

 function cancelSuspendDelay() {
   try {
     backgroundTaskManager.cancelSuspendDelay(id);
   } catch (error) {
     console.error(`cancelSuspendDelay failed. code: ${(error as BusinessError).code}, message: ${(error as BusinessError).message}`);
   }
 }

使用习惯:

  • 业务自然结束时主动 cancel
  • 系统回调里(即将超时)也要 cancel 双保险,保护配额 & 避免被系统惩罚。

4. 实战流程(可以脑补时序)

  1. 前台 / onBackground() 里:

    • 调用 requestSuspendDelay() → 拿到 id
  2. 正常执行你的后台收尾逻辑(例如保存 / 发消息)。

  3. (可选)根据 getRemainingDelayTime(id) 判断要不要继续做其它任务。

  4. 业务完成:

    • 主动 cancelSuspendDelay(id)
  5. 如果忘了取消,快超时时系统会调用你传的 callback

    • 在 callback 里做最后清理 + 再次 cancelSuspendDelay(id)