记录 Dart 实现定时任务的几种方式

Timer.Periodic()

1
Timer Timer.periodic(Duration duration, void Function(Timer) callback)

该方法接受持续时间和回调函数参数

eg:

1
2
3
4
5
6
7
8
9
import 'dart:async';

main() {
const oneMinute = Duration(minutes: 1);
Timer.periodic(oneMinute, (Timer t) {
print('Hello Welcome: ' + new DateTime.now().toString());
});
}

Stream.periodic()

  • take(n) 方法在Stream对象上允许执行n次的计数。
  • listen() 事件捕获发射的事件并执行函数。箭头函数被用来执行。
1
2
3
4
5
6
7
8
9
10
11
import 'dart:async';

main() {
StreamSubscription streamSubscription;

const oneSecond = Duration(seconds: 1);

streamSubscription = new Stream.periodic(oneSecond)
.take(5)
.listen((_) => print('Hello Welcome: ' + new DateTime.now().toString()));
}

Timer.Periodic()Stream.periodic() 都有一个问题 , 首次执行不是立即执行

这样在实际业务中使用起来就比较麻烦 , 要手动先执行一次 , 然后再开启循环 ,自己要手动判断是否开启循环 , 非常麻烦. 因此这里将采用 rxDart 加操作符来实现逻辑上的 interval

rxDart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
List<int> list = [1,2,3,4,5];
StreamSubscription<int>? mTimerSub;

mTimerSub = Stream.fromIterable(List.generate(
list, (index) => index + 1))
.interval(const Duration(seconds: 3))
.startWith(list.first)
.take(list.length)
.listen((i) {
final item = list[i];
_executeTask(item);
});
mTimerSub?.onDone(() {
print('done!!!');
});

这里是将遍历一个 index 比原数组大1的数组,然后根据 index 取数组元素执行 .

startWith 是将立即执行第一个元素 , 然后下一次取数据直接从 1 的位置取 , 从而达到了常规 rxinterval 效果 , 且总数可控.