Flutter进阶(4):定时器使用(Timer)
一、Timer简介
Flutter 的 Timer 类是 Dart 语言中的一个内置类,用于创建定时器。定时器可以用于在一段时间后执行代码,或者以固定的时间间隔重复执行代码。Timer 类提供了一种简单的方式来管理这些时间相关的任务。
二、Timer类的详细介绍
2.1 导入dart:async包
要使用 Timer 类,首先需要导入dart:async
包,因为它包含了定时器相关的类和函数。
import 'dart:async';
2.2 创建一个定时器
使用 Timer 类的构造函数可以创建一个定时器。构造函数有两个参数,分别是持续时间(Duration)和回调函数(void Function())。
Timer(Duration duration, void Function() callback)
- duration 参数表示定时器的持续时间,即多长时间后触发回调函数。
- callback 参数是一个函数,它定义了当定时器触发时要执行的代码。
例如,以下代码创建一个在2秒后执行的定时器:
Timer(Duration(seconds: 2), () {
print("定时器已触发");
});
2.3 取消定时器
你可以随时取消定时器,以防止回调函数执行。Timer 对象有一个cancel()
方法,可以用来取消定时器。
Timer myTimer = Timer(Duration(seconds: 2), () {
print("定时器已触发");
});
// 取消定时器
myTimer.cancel();
2.4 定时器的周期性执行
如果你想要定时器在固定的时间间隔内重复执行,可以使用periodic
构造函数。它与 Timer 构造函数类似,但是会重复触发回调函数。
Timer.periodic(Duration(seconds: 2), (Timer timer) {
print("定时器已触发");
});
在上面的例子中,回调函数每 2 秒执行一次。
2.5 注意事项
- 定时器的回调函数会在一个隔离的事件循环中执行,不会阻塞主事件循环。
- 定时器的精确性依赖于系统的可用性和负载,因此可能会有一些偏差。
- 如果需要在主 UI 线程中执行操作,例如更新 UI,你需要确保使用
setState()
或runOnUiThread()
等机制。
三、计时器示例
下面使用 flutter 实现一个好看的计时器。先看下效果图:
main.dart 文件,代码如下:
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) => const MaterialApp(
title: "My Stopwatch",
home: StopwatchApp());
}
class StopwatchApp extends StatefulWidget {
const StopwatchApp({super.key});
@override
State<StopwatchApp> createState() => _StopwatchAppState();
}
class _StopwatchAppState extends State<StopwatchApp> {
String timeString = "00:00:00";
Stopwatch stopwatch = Stopwatch();
late Timer timer; // 定义定时器
// 开始计时
void start() {
stopwatch.start();
timer = Timer.periodic(const Duration(milliseconds: 100), update);
}
// 更新计时
void update(Timer t) {
if (stopwatch.isRunning) {
setState(() {
// 拼接时间字符串
timeString =
(stopwatch.elapsed.inMinutes % 60).toString().padLeft(2, "0") +
":" +
(stopwatch.elapsed.inSeconds % 60).toString().padLeft(2,
"0") +
":" +
(stopwatch.elapsed.inMilliseconds % 1000 / 10).clamp(0, 99)
.toStringAsFixed(0)
.padLeft(2, "0");
});
}
}
// 停止计时
void stop() {
setState(() {
timer.cancel();
stopwatch.stop();
});
}
// 重置计时
void reset() {
timer.cancel();
stopwatch.reset();
setState(() {
timeString = "00:00:00";
});
stopwatch.stop();
}
@override
Widget build(BuildContext context) {
return Scaffold (
appBar: AppBar(
title: const Text("My Stopwatch"),
),
backgroundColor: Colors.blue,
body: Column(
children: <Widget> [
Padding(padding: const EdgeInsets.symmetric(horizontal: 80,
vertical: 60),
child: Text("STOPWATCH",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.grey.shade900,
)
),
),
Expanded(
child: Container(
width: 250,
height: 250,
decoration: BoxDecoration(
color: Colors.pink,
shape: BoxShape.circle,
boxShadow: [
const BoxShadow(
offset: Offset(10,10),
color: Colors.red,
blurRadius: 5),
BoxShadow(
offset: const Offset(-10,-10),
color: Colors.white.withOpacity(0.85),
blurRadius: 5)
]),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('$timeString',
style: TextStyle(
fontSize: 40,
color: Colors.grey.shade900,
)
)
],
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical:
60),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
TextButton(
onPressed: reset,
child: Container(
height: 100,
width: 100,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: const Icon(Icons.refresh, size: 60),
)
),
TextButton(
onPressed: () => {
stopwatch.isRunning ? stop() : start()
},
child: Container(
height: 100,
width: 100,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: Icon(stopwatch.isRunning ? Icons.pause :
Icons.play_arrow, size: 60),
),
)
],
),
)
],
)
);
}
}
四、倒计时示例
如下图所示为常见 App 的一个启动页面的倒计时显示效果:
全部代码如下:
import 'package:flutter/material.dart';
import 'dart:async';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("Timer"),
),
body: const TimerDemo(),
),
);
}
}
class TimerDemo extends StatefulWidget {
const TimerDemo({super.key});
@override
State<TimerDemo> createState() => _TimerDemoState();
}
class _TimerDemoState extends State<TimerDemo> {
// 声明变量
late Timer _timer;
// 记录当前的时间
int curentTimer = 0;
@override
void initState() {
super.initState();
// 循环执行
// 间隔100ms
_timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
// 自增
curentTimer += 100;
// 到5秒后重新计时
if (curentTimer > 5000) {
curentTimer = 0;
//_timer.cancel();
}
setState(() {});
});
}
@override
void dispose() {
// 取消计时器
_timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("倒计时"),
),
backgroundColor: Colors.white,
// 填充布局
body: Container(
padding: const EdgeInsets.all(20),
width: double.infinity,
height: double.infinity,
child: Column(
children: [
// 层叠布局将进度与文字叠在一起
Stack(
// 子Widget居中
alignment: Alignment.center,
children: [
// 圆形进度
CircularProgressIndicator(
// 当前指示的进度 0.0 -1.0
value: curentTimer / 5000,
),
// 显示的文本
Text("${(curentTimer / 1000).toInt()}"),
],
)
],
)),
);
}
}