Skip to content
Inspire - Capo Productions

定时器

延时器

类似 JS 的 setTimeout,在指定时间后执行一次回调。

Future.delayed

dart
// 页面加载后延迟执行
@override
void initState() {
  super.initState();

  Future.delayed(Duration(milliseconds: 300), () {
    print('300ms 后执行');
  });
}

支持 async/await:

dart
await Future.delayed(Duration(milliseconds: 300));
print('300ms 后执行');

周期器

类似 JS 的 setInterval,每隔指定时间执行一次回调。

示例一:轮询获取数据

dart
import 'dart:async';

late Timer timer;

@override
void initState() {
  super.initState();
  // initState 只执行一次,所以不需要取消 Timer
  timer = Timer.periodic(Duration(seconds: 5), (_) {
    fetchData();
  });
}

@override
void dispose() {
  // 取消定时器
  timer.cancel();
  super.dispose();
}

示例二:倒计时按钮

dart
import 'dart:async';
import 'package:flutter/material.dart';

class CountdownButton extends StatefulWidget {
  @override
  State<CountdownButton> createState() => _CountdownButtonState();
}

class _CountdownButtonState extends State<CountdownButton> {
  Timer? _timer;
  int _countdown = 10;

  void _startTimer() {
    _timer?.cancel(); // 可能多次执行 _startTimer 方法,所以需要避免重复启动
    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      if (_countdown == 0) {
        timer.cancel();
      } else {
        setState(() {
          _countdown--;
        });
      }
    });
  }

  @override
  void dispose() {
    _timer?.cancel(); // 页面销毁时一定要关闭Timer!
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: _startTimer,
      child: Text(_countdown == 0 ? '重新发送' : '$_countdown 秒'),
    );
  }
}

常见注意事项

⚠️ 问题💡 解决方案
Widget 销毁后 Timer 仍在运行必须在 dispose() 中调用 _timer?.cancel()
多次启动重复计时启动前先 _timer?.cancel()
UI 不更新在回调中使用 setState() 更新界面
后台仍在运行如果页面不需要继续计时,应在离开页面时取消 Timer

延迟执行 + 循环执行

dart
Future.delayed(Duration(seconds: 1), () {
  Timer.periodic(Duration(seconds: 2), (timer) {
    print('执行一次');
  });
});