「鸿蒙 NEXT」基于 taskpool 实现自定义 Timer 工具类

前言

之前在使用原生的 Timer 定时器实现定时任务时,发现当切换页面或应用切换至后台时,Timer 也会被冻结。如何实现可全局调用,支持后台执行的定时任务呢?我想到了使用 taskpool 任务池实现定时任务,在熟练使用 taskpool 实现定时任务后,进一步将其封装为一个自定义 Timer 工具类方便复用。

实现技术

  • 基于 API 12 ,理论上 13 和 14 版本也可以正常使用;
  • taskpool 多线程任务池,原生 Timer 的替代方案,该 API 下有 executeDelayed() 和 executePeriodically() 方法分别可以实现延时任务和周期任务;
  • emitter 事件订阅,类似安卓开发的 eventbus。由于 taskpool 构造时传入的函数,仅允许序列化支持类型作为入参,于是借助 emitter 做一层中转,通知到自定义 Timer 类触发相应的回调。

实现代码

新建文件 FuTimer.ets,所有实现代码写在同一文件下就好。

  1. 设计定时器的回调接口,在接收到 onTask() 回调时,调用需要定时/周期性执行的任务方法:
typescript 复制代码
export interface TimerCallback {
  onStart: () => void;  // 定时器开始
  onCancel: () => void; // 定时器取消
  onTask: () => void;   // 定时任务触发时的回调
}
  1. 自定义工具类 Timer 实现:
kotlin 复制代码
import { taskpool } from "@kit.ArkTS"
import { BusinessError, emitter, systemDateTime } from "@kit.BasicServicesKit";

export class Timer {
  public constructor(callback: TimerCallback) {
    this.timerName =  `futimer_${systemDateTime.getTime()}`;
    this.timerCallback = callback;

    emitter.on(this.timerName, () => {
      if (this.timerCallback) {
        this.timerCallback.onTask();
      }
    });
  }

  private timerName: string;  // 自定义 Timer 唯一名称,与 emitter 订阅事件绑定
  private timerTask: taskpool.Task | undefined;
  private timerCallback: TimerCallback | undefined;

  /*
   * isRepeat: 是否重复执行任务,false 只执行一次, true 会周期性地执行
   * interval:任务执行间隔时间
   */
  public start(isRepeat: boolean, interval: number) {
    // 取消该定时器上一个任务
    if (this.timerTask) {
      this.cancel();
    }
    
    // 开始执行当前任务
    if (this.timerCallback) {
      this.timerCallback.onStart();
    } else {
      return;
    }
    
    // 重置定时任务
    this.timerTask = new taskpool.Task(executeTask, this.timerName);
    if (isRepeat) {
      taskpool.executePeriodically(interval, this.timerTask);
    } else {
      taskpool.executeDelayed(interval, this.timerTask);
    }
  }

  public cancel() {
    try {
      if (this.timerTask) {
        taskpool.cancel(this.timerTask);
      }
    } catch (e) {
      let error = e as BusinessError;
    } finally {
      this.timerTask = undefined;
      if (this.timerCallback) {
        this.timerCallback.onCancel();
      }
    }
  }

  // 销毁定时器,此时再调用 start() 方法无效
  public destroy() {
    this.cancel();
    emitter.off(this.timerName);
    this.timerTask = undefined;
    this.timerCallback = undefined;
  }
}

export interface TimerCallback {
  onStart: () => void;
  onCancel: () => void;
  onTask: () => void;
}

@Concurrent
function executeTask(timerName: string) {
  emitter.emit(timerName);
}

ps:工具类我写在模块下,需要在模块的 Index.ets 中将其 export 出来:

javascript 复制代码
export * as futimer from './src/main/ets/utils/FuTimer'

调用示例

现在使用封装好的定时器工具,实现一个简单的计时功能:

typescript 复制代码
import { futimer } from 'fusdk'; // fusdk 是我定义的本地模块依赖名称,这个不重要了

@Entry
@Component
struct Index {
  @State count: number = 0;

  @State timer: futimer.Timer = new futimer.Timer({
    onStart: () => {
      console.debug('定时器启动');
    },
    onCancel: () => {
      console.debug('定时器取消');
    },
    onTask: () => {
      this.count++;
      console.debug(`第 ${this.count} 次执行任务`);
    }
  });

  build() {
    Column() {
      Text(`现在是第 ${this.count} 秒`)

      Button('开始计时')
        .onClick(() => {
          this.timer.start(true, 1000);
        })

      Button('暂停计时')
        .onClick(() => {
          this.timer.cancel();
        })
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.SpaceEvenly)
  }
}

效果图:

结语

笔者也是正在学习鸿蒙 NEXT 开发的小菜鸟一枚,希望分享的内容能对你有帮助,也欢迎给予建议,今后也会争取在这里分享更多鸿蒙 NEXT 开发相关的内容和经验。

相关推荐
ok406lhq22 分钟前
[鸿蒙2025领航者闯关] 我的鸿蒙SDK领航者养成记
华为·harmonyos·鸿蒙2025领航者闯关·鸿蒙6实战·开发者年度总结
嗝o゚3 小时前
Flutter 到鸿蒙开发:3个月技能迁移指南
flutter·华为·harmonyos
二流小码农4 小时前
鸿蒙开发:上架困难?谈谈我的上架之路
android·ios·harmonyos
luxy20044 小时前
HarmonyOS 5.0 AT指令4G透传控制器
华为·harmonyos
御承扬5 小时前
鸿蒙原生系列之动画效果(属性动画)
华为·harmonyos·动画效果
江澎涌6 小时前
JWorker——一套简单易用的基于鸿蒙 Worker 的双向 RPC 通讯机制
typescript·harmonyos·arkts
晚霞的不甘6 小时前
Flutter + OpenHarmony 国际化与无障碍(i18n & a11y)深度实践:打造真正包容的鸿蒙应用
flutter·华为·harmonyos
威哥爱编程14 小时前
【鸿蒙开发案例篇】定点出击!鸿蒙6.0视频碰一碰流转+实时进度同步案例
harmonyos·arkts·arkui
嗝o゚16 小时前
鱼与熊掌可兼得?用Flutter+鸿蒙的混合架构破解性能与UI的世纪难题
flutter·架构·harmonyos
遇到困难睡大觉哈哈18 小时前
HarmonyOS 应用数据持久化概述:Preferences、KV-Store、RelationalStore 到底怎么选?
笔记·华为·harmonyos