Flutter 学习之旅 之 flutter 实现简单自定义的倒计时 CountdownTimer 功能/监听倒计时开始/结束/计时中的事件
目录
Flutter 学习之旅 之 flutter 实现简单自定义的倒计时 CountdownTimer 功能/监听倒计时开始/结束/计时中的事件
一、简单介绍
Flutter 是一款开源的 UI 软件开发工具包,由 Google 开发和维护。它允许开发者使用一套代码同时构建跨平台的应用程序,包括移动设备(iOS 和 Android)、Web 和桌面平台(Windows、macOS 和 Linux)。
Flutter 使用 Dart 编程语言,它可以将代码编译为 ARM 或 Intel 机器代码以及 JavaScript,从而实现快速的性能。Flutter 提供了一个丰富的预置小部件库,开发者可以根据自己的需求灵活地控制每个像素,从而创建自定义的、适应性强的设计,这些设计在任何屏幕上都能呈现出色的外观和感觉。
二、CountdownTimer
CountdownTimer
是一个封装好的倒计时工具类,用于实现倒计时功能。它支持自定义倒计时总时长,并通过回调函数提供倒计时开始、结束以及每秒事件的处理能力。此外,还支持暂停、继续、停止和重置倒计时的操作,方便在不同场景下灵活控制倒计时过程。在 Flutter 应用中,通过简单的调用即可实现复杂的倒计时逻辑,适用于验证码倒计时、活动倒计时等多种场景。
在开发和使用
CountdownTimer
时,需要注意以下几点:1、开发注意事项
避免内存泄漏:
确保在倒计时结束或页面销毁时取消定时器(
_timer?.cancel()
),避免定时器继续运行导致内存泄漏。在
dispose
方法中释放资源,例如:@override void dispose() { _countdownTimer.stop(); super.dispose(); }
线程安全:
Timer
是基于 Dart 的单线程模型运行的,因此不需要额外处理线程安全问题。但要确保在回调中更新 UI 时使用setState
或其他合适的响应式方法。避免重复启动:
在调用
start
方法之前,建议先调用stop
方法,确保不会重复启动定时器。例如:void start() { stop(); _remainingTime = _duration; _isPaused = false; onStart(); _startTimer(); }
处理暂停和继续逻辑:
暂停时取消定时器,并设置
_isPaused = true
。继续时重新启动定时器,并确保
_isPaused = false
。回调函数的使用:
确保回调函数(
onStart
、onEnd
、onTick
)不会抛出异常,否则可能导致定时器无法正常工作。2、使用注意事项
初始化参数:
在初始化
CountdownTimer
时,确保传入的duration
参数大于 0,否则倒计时无法正常工作。按钮状态管理:
在 UI 中,根据倒计时的状态(开始、暂停、继续、停止)动态更新按钮的可用状态,避免用户误操作。例如:
bool isCounting = false; bool isPaused = false; void start() { isCounting = true; isPaused = false; _countdownTimer.start(); } void pause() { isPaused = true; _countdownTimer.pause(); } void resume() { isPaused = false; _countdownTimer.resume(); } void stop() { isCounting = false; _countdownTimer.stop(); }
避免重复调用:
在 UI 中,确保不会重复调用
start
方法。例如,可以使用一个标志位来判断倒计时是否已经在运行。倒计时结束后重置:
如果需要在倒计时结束后重新开始,建议调用
reset
方法重置倒计时。测试边界条件:
测试倒计时的边界条件,例如:
倒计时时间非常短(如 1 秒)。
倒计时时间非常长(如数小时)。
在倒计时过程中频繁暂停和继续。
适配不同设备:
确保倒计时在不同设备(如手机、平板、Web)上表现一致,特别是在时间精度和 UI 更新方面。
用户反馈:
在倒计时过程中,为用户提供明确的反馈,例如显示剩余时间、倒计时结束的提示等。
通过注意以上事项,可以确保
CountdownTimer
在开发和使用过程中更加稳定、可靠,并且能够满足各种实际需求。
三、简单效果展示
四、简单案例实现
1、这里使用 Android Studio 进行创建 Flutter 项目
2、创建一个 application 的 Flutter 项目
3、初次的项目结构如下
4、编写实现 CountdownTimer 功能
5、在 main 中测试 倒计时功能
6、连接设备,运行效果如下
五、关键代码
1、CountdownTimer
import 'dart:async';
import 'package:flutter/material.dart';
class CountdownTimer {
int _duration; // 倒计时总时长(单位:秒)
Timer? _timer; // 定时器对象,用于每秒触发一次事件
int _remainingTime = 0; // 剩余时间(单位:秒)
bool _isPaused = false; // 标志,表示倒计时是否处于暂停状态
// 回调函数
final VoidCallback onStart; // 倒计时开始时触发的回调
final VoidCallback onEnd; // 倒计时结束时触发的回调
final ValueChanged<int> onTick; // 每秒触发的回调,参数为剩余时间
// 构造函数,初始化倒计时总时长和回调函数
CountdownTimer({
required int duration, // 倒计时时间(单位:秒)
required this.onStart, // 倒计时开始事件
required this.onEnd, // 倒计时结束事件
required this.onTick, // 倒计时期间秒事件
}) : _duration = duration;
// 开始倒计时
void start() {
// 首先调用 stop 方法,确保之前的倒计时(如果存在)被停止
stop();
// 将剩余时间设置为倒计时总时长
_remainingTime = _duration;
// 将暂停标志设置为 false
_isPaused = false;
// 触发倒计时开始事件
onStart();
// 调用内部方法 _startTimer,启动定时器
_startTimer();
}
// 暂停倒计时
void pause() {
// 将暂停标志设置为 true
_isPaused = true;
// 取消当前的定时器
_timer?.cancel();
}
// 继续倒计时
void resume() {
// 检查是否处于暂停状态
if (_isPaused) {
// 将暂停标志设置为 false
_isPaused = false;
// 调用内部方法 _startTimer,重新启动定时器
_startTimer();
}
}
// 停止倒计时
void stop() {
// 取消当前的定时器
_timer?.cancel();
// 将剩余时间设置为 0
_remainingTime = 0;
// 将暂停标志设置为 false
_isPaused = false;
}
// 重置倒计时
void reset() {
// 调用 stop 方法,停止倒计时
stop();
// 将剩余时间设置为倒计时总时长
_remainingTime = _duration;
}
// 内部方法:启动定时器
void _startTimer() {
// 创建一个每秒触发一次的定时器
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
// 检查是否处于暂停状态,且剩余时间是否大于 0
if (!_isPaused && _remainingTime > 0) {
// 减少剩余时间
_remainingTime--;
// 触发每秒事件,将剩余时间作为参数传递
onTick(_remainingTime);
} else if (_remainingTime <= 0) {
// 如果剩余时间小于或等于 0,取消定时器
timer.cancel();
// 触发倒计时结束事件
onEnd();
}
});
}
}
代码说明:
变量定义:
_duration
:倒计时的总时长,单位为秒。
_timer
:Timer
对象,用于实现每秒触发一次的倒计时功能。
_remainingTime
:当前剩余的时间,单位为秒。
_isPaused
:布尔值,用于标记倒计时是否处于暂停状态。构造函数:
接收倒计时总时长和三个回调函数(
onStart
、onEnd
、onTick
)。初始化
_duration
为传入的倒计时总时长。
start
方法:
调用
stop
方法确保之前的倒计时被停止。将剩余时间设置为倒计时总时长。
将暂停标志设置为
false
。触发倒计时开始事件。
调用
_startTimer
方法启动定时器。
pause
方法:
将暂停标志设置为
true
。取消当前的定时器。
resume
方法:
检查是否处于暂停状态。
如果处于暂停状态,将暂停标志设置为
false
,并重新启动定时器。
stop
方法:
取消当前的定时器。
将剩余时间设置为 0。
将暂停标志设置为
false
。
reset
方法:
调用
stop
方法停止倒计时。将剩余时间设置为倒计时总时长。
_startTimer
内部方法:
创建一个每秒触发一次的定时器。
在定时器的回调中:
检查是否处于暂停状态,且剩余时间是否大于 0。
如果满足条件,减少剩余时间,并触发每秒事件。
如果剩余时间小于或等于 0,取消定时器并触发倒计时结束事件。
通过这些详细的注释,你可以更好地理解代码的逻辑和实现细节。
2、main
import 'package:flutter/material.dart';
import 'package:test_countdown_timer/countdown_timer.dart'; // 导入封装好的倒计时工具类
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('倒计时示例'), // 应用的标题
),
body: const CountdownExample(), // 倒计时示例页面
),
);
}
}
class CountdownExample extends StatefulWidget {
const CountdownExample({super.key});
@override
_CountdownExampleState createState() => _CountdownExampleState();
}
class _CountdownExampleState extends State<CountdownExample> {
late CountdownTimer _countdownTimer; // 倒计时工具类实例
int _remainingTime = 60; // 默认倒计时时间(单位:秒)
@override
void initState() {
super.initState();
// 初始化倒计时工具类实例,传入默认倒计时时间以及各个回调函数
_countdownTimer = CountdownTimer(
duration: _remainingTime,
onStart: () {
print('倒计时开始'); // 倒计时开始时打印日志
},
onEnd: () {
print('倒计时结束'); // 倒计时结束时打印日志
},
onTick: (remainingTime) {
setState(() {
_remainingTime = remainingTime; // 更新剩余时间
});
},
);
}
@override
void dispose() {
_countdownTimer.stop();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center, // 垂直居中对齐
children: <Widget>[
Text('倒计时: $_remainingTime 秒'), // 显示剩余时间
ElevatedButton(
onPressed: () {
_countdownTimer.start(); // 调用倒计时工具类的 start 方法开始倒计时
},
child: const Text('开始倒计时'), // 按钮文本
),
ElevatedButton(
onPressed: () {
_countdownTimer.pause(); // 调用倒计时工具类的 pause 方法暂停倒计时
},
child: const Text('暂停倒计时'), // 按钮文本
),
ElevatedButton(
onPressed: () {
_countdownTimer.resume(); // 调用倒计时工具类的 resume 方法继续倒计时
},
child: const Text('继续倒计时'), // 按钮文本
),
ElevatedButton(
onPressed: () {
_countdownTimer.stop(); // 调用倒计时工具类的 stop 方法停止倒计时
},
child: const Text('停止倒计时'), // 按钮文本
),
ElevatedButton(
onPressed: () {
_countdownTimer.reset(); // 调用倒计时工具类的 reset 方法重置倒计时
setState(() {
_remainingTime = 60; // 重置剩余时间为默认值
});
},
child: const Text('重置倒计时'), // 按钮文本
),
],
),
);
}
}
详细注释说明:
导入模块:
import 'package:flutter/material.dart';
:导入 Flutter 的 Material 组件库,用于构建 UI。
import 'package:test_countdown_timer/countdown_timer.dart';
:导入封装好的倒计时工具类CountdownTimer
。
main
函数:
void main() { runApp(const MyApp()); }
:应用的入口点,启动应用。
MyApp
类:
class MyApp extends StatelessWidget
:定义一个无状态的 Flutter 应用。
build
方法:构建应用的根组件,包含一个Scaffold
,其appBar
显示标题,body
显示倒计时示例页面。
CountdownExample
类:
class CountdownExample extends StatefulWidget
:定义一个有状态的倒计时示例页面。
_CountdownExampleState
类:CountdownExample
的状态类,用于管理倒计时的状态。
_CountdownExampleState
类:
_countdownTimer
:倒计时工具类的实例。
_remainingTime
:当前剩余时间,初始值为 60 秒。
initState
方法:初始化倒计时工具类实例,传入默认倒计时时间以及各个回调函数。
onStart
:倒计时开始时触发的回调,打印日志。
onEnd
:倒计时结束时触发的回调,打印日志。
onTick
:每秒触发的回调,更新剩余时间并调用setState
刷新 UI。
build
方法:构建倒计时示例页面的 UI,包含一个显示剩余时间的文本和五个按钮,分别用于控制倒计时的开始、暂停、继续、停止和重置。按钮功能:
开始倒计时
:调用_countdownTimer.start()
方法开始倒计时。
暂停倒计时
:调用_countdownTimer.pause()
方法暂停倒计时。
继续倒计时
:调用_countdownTimer.resume()
方法继续倒计时。
停止倒计时
:调用_countdownTimer.stop()
方法停止倒计时。
重置倒计时
:调用_countdownTimer.reset()
方法重置倒计时,并将剩余时间重置为默认值。通过这些详细的注释,你可以更好地理解代码的逻辑和实现细节。