HarmonyOS应用开发实战:猫猫大作战-workScheduler 的使用
·


前言
workScheduler(工作调度器)是 BackgroundTasksKit 中用于执行延迟/周期任务的能力。与 startBackgroundRunning 的持续运行不同,workScheduler 适合定时触发的短任务——如每日战绩上传、每周排行榜刷新、缓存清理等。
在「猫猫大作战」中,我们使用 workScheduler 实现每日定时上传战绩到云端,确保玩家的高分不会丢失,同时为未来的跨设备同步打下基础。
本文以「猫猫大作战」的定时战绩上传为锚点,讲解 workScheduler 的完整使用方法,包括WorkInfo 配置、任务注册和取消、WorkAbility 实现、以及约束条件设置。
提示:本系列不讲 ArkTS 基础语法与环境搭建。本篇是阶段五第 163 篇。
一、workScheduler 基础
1.1 WorkInfo 配置
import { workScheduler } from '@kit.BackgroundTasksKit';
async function scheduleSync(context: Context): Promise<void> {
const workInfo: workScheduler.WorkInfo = {
workId: 1001, // 任务唯一 ID
bundleName: 'com.maomaodazuozhan.game', // 包名
abilityName: 'SyncWorkAbility', // 执行任务的 Ability
networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI, // 网络条件
isPersisted: true, // 重启后是否保留
repeatCycleTime: 24 * 60 * 60 * 1000, // 24 小时周期
};
try {
await workScheduler.startWork(workInfo);
console.info(`工作调度器已启动, workId: ${workInfo.workId}`);
} catch (err) {
console.error(`启动工作调度失败: ${err.message}`);
}
}
1.2 参数详解
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
workId |
number | ✅ | 任务唯一标识,同一应用内不可重复 |
bundleName |
string | ✅ | 应用包名,与应用配置一致 |
abilityName |
string | ✅ | 执行后台任务的 Ability 类名 |
networkType |
NetworkType | ❌ | 网络条件约束(WIFI/移动数据/不限) |
isPersisted |
boolean | ❌ | 设备重启后是否保留该任务 |
repeatCycleTime |
number | ❌ | 循环周期(毫秒),不设为单次任务 |
提示:
workId在同一个应用中必须唯一。建议用递增数字管理,或使用模块编号(如 1001=战绩上传、1002=排行榜刷新)。
二、WorkAbility 实现
2.1 创建 WorkAbility
// entry/src/main/ets/entryability/SyncWorkAbility.ets
import { WorkSchedulerAbility, workScheduler } from '@kit.BackgroundTasksKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
export default class SyncWorkAbility extends WorkSchedulerAbility {
private TAG = 'SyncWork';
private DOMAIN = 0xFF00;
onWorkStart(workInfo: workScheduler.WorkInfo): void {
hilog.info(this.DOMAIN, this.TAG,
`后台任务启动: workId=${workInfo.workId}`);
// 执行具体的后台任务
this.executeSyncTask().then(() => {
hilog.info(this.DOMAIN, this.TAG, '后台任务执行完成');
}).catch((err) => {
hilog.error(this.DOMAIN, this.TAG, `后台任务失败: ${err.message}`);
});
}
onWorkStop(workInfo: workScheduler.WorkInfo): void {
hilog.info(this.DOMAIN, this.TAG,
`后台任务停止: workId=${workInfo.workId}`);
// 清理资源
}
private async executeSyncTask(): Promise<void> {
// 1. 读取本地战绩
const localData = await this.readLocalScores();
// 2. 上传到服务端
await this.uploadToCloud(localData);
// 3. 清理过期缓存
await this.cleanCache();
}
private async readLocalScores(): Promise<object> {
// 从 RDB 或 Preferences 读取
return { /* ... */ };
}
private async uploadToCloud(data: object): Promise<void> {
// 调用网络 API 上传
hilog.info(this.DOMAIN, this.TAG, '上传战绩数据');
}
private async cleanCache(): Promise<void> {
// 清理 7 天前的缓存
hilog.info(this.DOMAIN, this.TAG, '清理缓存');
}
}
2.2 module.json5 注册
{
module: {
abilities: [
{
name: 'SyncWorkAbility',
srcEntry: './ets/entryability/SyncWorkAbility.ets',
description: '$string:SyncWorkAbility_desc',
icon: '$media:icon',
label: '$string:SyncWorkAbility_label',
type: 'workScheduler',
exported: false,
},
// ...
],
}
}
三、任务注册和管理
3.1 启动任务
export class SyncManager {
// 每日战绩上传任务
static readonly SYNC_WORK_ID = 1001;
// 每日排行榜刷新任务
static readonly RANK_WORK_ID = 1002;
static async startDailySync(context: Context): Promise<void> {
const workInfo: workScheduler.WorkInfo = {
workId: this.SYNC_WORK_ID,
bundleName: context.abilityInfo.bundleName,
abilityName: 'SyncWorkAbility',
networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
isPersisted: true,
repeatCycleTime: 24 * 60 * 60 * 1000, // 24h
};
await workScheduler.startWork(workInfo);
}
static async startWeeklyRank(context: Context): Promise<void> {
const workInfo: workScheduler.WorkInfo = {
workId: this.RANK_WORK_ID,
bundleName: context.abilityInfo.bundleName,
abilityName: 'SyncWorkAbility', // 可复用相同的 Ability
networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
isPersisted: true,
repeatCycleTime: 7 * 24 * 60 * 60 * 1000, // 7d
};
await workScheduler.startWork(workInfo);
}
}
3.2 停止和查询任务
// 停止单个任务
async function stopSyncWork(context: Context): Promise<void> {
try {
await workScheduler.stopWork(
context,
SyncManager.SYNC_WORK_ID,
true // true = 取消已等待但未执行的任务
);
console.info('定时同步已停止');
} catch (err) {
console.error(`停止任务失败: ${err.message}`);
}
}
// 查询任务状态
async function isWorkScheduled(workId: number): Promise<boolean> {
try {
const isScheduled = await workScheduler.isWorkScheduled(workId);
console.info(`任务 ${workId}: ${isScheduled ? '已调度' : '未调度'}`);
return isScheduled;
} catch (err) {
console.error(`查询任务状态失败: ${err.message}`);
return false;
}
}
// 获得所有已调度的任务
async function getAllScheduledWorks(context: Context): Promise<workScheduler.WorkInfo[]> {
return await workScheduler.getAllScheduledWorks(context);
}
3.3 约束条件
// 网络类型约束
enum NetworkType {
NETWORK_TYPE_ANY, // 不限(WIFI 或移动数据)
NETWORK_TYPE_MOBILE, // 仅移动数据
NETWORK_TYPE_WIFI, // 仅 WIFI(推荐)
}
// 其他约束(可通过 WorkInfo 设置)
interface WorkInfo {
// ...
batteryLevel?: number; // 电量阈值(如 20% 以上才执行)
isCharging?: boolean; // 是否仅充电时执行
storageLevel?: number; // 存储空间阈值
}
| 约束 | 类型 | 说明 | 推荐值 |
|---|---|---|---|
networkType |
NetworkType | 网络条件 | WIFI(节省流量) |
batteryLevel |
number | 最低电量百分比 | 20 |
isCharging |
boolean | 是否需充电状态 | false |
storageLevel |
number | 最低存储百分比 | 10 |
四、性能与节电
4.1 任务执行限制
// workScheduler 任务的限制:
// 1. 每次执行最长 2 分钟(超时自动停止)
// 2. 单应用每日总执行时长有限制
// 3. 频率不宜过高(建议 ≥ 1 小时)
// ✅ 推荐的周期任务间隔
const RECOMMENDED_INTERVALS = {
HOURLY: 60 * 60 * 1000, // 1 小时
DAILY: 24 * 60 * 60 * 1000, // 24 小时(推荐)
WEEKLY: 7 * 24 * 60 * 60 * 1000, // 7 天
};
4.2 省电策略
// 省电建议
// 1. WIFI 下执行(避免消耗移动数据)
networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
// 2. 仅充电时执行(适合大数据量同步)
const workInfo: workScheduler.WorkInfo = {
// ...
isCharging: true,
};
// 3. 合并多个任务到同一个 WorkAbility
// 避免启动多个独立的后台任务,用一个 Ability 处理多个操作
export default class UnifiedWorkAbility extends WorkSchedulerAbility {
onWorkStart(workInfo: workScheduler.WorkInfo): void {
switch (workInfo.workId) {
case 1001: this.syncScores(); break;
case 1002: this.refreshRank(); break;
case 1003: this.cleanCache(); break;
}
}
}
五、常见场景
5.1 每日签到提醒
async function scheduleDailyReminder(context: Context): Promise<void> {
const workInfo: workScheduler.WorkInfo = {
workId: 2001,
bundleName: context.abilityInfo.bundleName,
abilityName: 'ReminderWorkAbility',
isPersisted: true,
repeatCycleTime: 24 * 60 * 60 * 1000,
};
await workScheduler.startWork(workInfo);
}
5.2 战绩云同步
// 游戏结束时触发一次同步(非周期任务)
async function syncAfterGame(context: Context, score: number): Promise<void> {
// 立即同步一次
const workInfo: workScheduler.WorkInfo = {
workId: 3001,
bundleName: context.abilityInfo.bundleName,
abilityName: 'SyncWorkAbility',
networkType: workScheduler.NetworkType.NETWORK_TYPE_WIFI,
// 不设 repeatCycleTime → 单次任务
};
await workScheduler.startWork(workInfo);
}
六、调试方法
// 使用 hdc 命令调试 workScheduler
// hdc shell
// hdc shell aa start -b com.maomaodazuozhan.game -a SyncWorkAbility
// 查看已调度的任务
async function debugScheduledWorks(context: Context): Promise<void> {
const works = await workScheduler.getAllScheduledWorks(context);
console.info(`当前已调度 ${works.length} 个后台任务:`);
for (const w of works) {
console.info(` workId=${w.workId}, ability=${w.abilityName}, ` +
`repeat=${w.repeatCycleTime}ms, persisted=${w.isPersisted}`);
}
}
七、常见问题
| 问题 | 原因 | 解决 |
|---|---|---|
| 任务未按时执行 | 系统省电限制 | 使用 isPersisted=true 并设置合理触发条件 |
| WorkAbility 未启动 | module.json5 配置错误 | 检查 ability 的 type 和 class 名称 |
| workId 冲突 | 重复 ID | 每个任务使用唯一 ID |
| 后台任务执行超时 | 任务超过 2 分钟 | 拆分大任务、控制在 1 分钟内完成 |
| 设备重启后任务丢失 | isPersisted=false |
设置为 true |
八、与其他后台方案对比
| 方案 | 用途 | 执行时长 | 周期能力 | 保活 | 电量消耗 |
|---|---|---|---|---|---|
| workScheduler | 延迟/周期任务 | ≤ 2 分钟 | ✅ 支持 | 不保活 | 低 |
| startBackgroundRunning | 持续后台任务 | 长时间 | ❌ | 需保活 | 高 |
| continuousTask | 短暂任务 | ≤ 3 分钟 | ❌ | 不保活 | 中 |
| 前台 Service | 前台可见任务 | 无限 | ❌ | 系统保活 | 中 |
九、最佳实践
- 优先使用 WIFI:
networkType: NETWORK_TYPE_WIFI节省用户流量 - 周期合理:日常任务 24h 周期,避免小于 1 小时
- isPersisted=true:设备重启后自动恢复定时任务
- 统一 WorkAbility:用 switch 分发不同 workId,减少 Ability 数量
- 任务轻量化:单次执行控制在 30 秒内,避免超时
- 错误处理:任务内 try-catch,防止未捕获异常导致任务提前终止
- 电量感知:低电量或非充电时减少执行
// 最佳实践示例
async function scheduleBestPractice(context: Context): Promise<void> {
const isCharging = await getBatteryStatus();
const networkType = isCharging
? workScheduler.NetworkType.NETWORK_TYPE_ANY
: workScheduler.NetworkType.NETWORK_TYPE_WIFI;
const workInfo: workScheduler.WorkInfo = {
workId: 1001,
bundleName: context.abilityInfo.bundleName,
abilityName: 'SyncWorkAbility',
networkType,
isPersisted: true,
repeatCycleTime: 24 * 60 * 60 * 1000,
};
await workScheduler.startWork(workInfo);
}
十、完整集成示例
@Entry
@Component
struct GameEntry {
aboutToAppear() {
this.initBackgroundTasks();
}
async initBackgroundTasks() {
const ctx = getContext() as common.UIAbilityContext;
// 启动每日战绩同步
await SyncManager.startDailySync(ctx);
// 启动每周排行榜刷新
await SyncManager.startWeeklyRank(ctx);
console.info('后台任务初始化完成');
}
// 游戏结束时触发一次同步
async onGameEnd(score: number) {
await syncAfterGame(getContext() as common.UIAbilityContext, score);
}
}
总结
workScheduler 是 HarmonyOS 中执行延迟/周期后台任务的推荐方案,适合每日数据同步、缓存清理等定时操作。核心要点:WorkInfo 配置任务参数、 WorkSchedulerAbility 执行具体逻辑、 isPersisted=true 保重启持久化、 WIFI 约束省流量、 任务控制在 2 分钟内、 统一 WorkAbility 分发不同 workId。
下一篇将深入 ReminderRequest——闹钟提醒的创建与管理。
如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!
相关资源:
更多推荐


所有评论(0)