如何使用Flutter Bloc实现每秒更新的天数统计功能
实现Bloc每秒更新流逝时长的方案
1. 新增承载实时时长的状态类
首先需要添加一个专门的状态,用来传递每秒计算出的流逝时长数据:
class OnTimerUpdateState extends DayCountingState { final int totalSeconds; final int days; final int hours; final int minutes; final int seconds; OnTimerUpdateState({ required this.totalSeconds, required this.days, required this.hours, required this.minutes, required this.seconds, }); }
2. 修改Bloc逻辑,加入定时器实现每秒更新
在Bloc中添加定时器变量存储初始日期,获取到初始日期后启动定时器,每秒计算时间差并发送状态更新:
class DayCountingBloc extends Bloc<DayCountingEvent, DayCountingState> { final RetrieveBeginDate _retrieveBeginDate; final StoreBeginDate _storeBeginDate; Timer? _updateTimer; DateTime? _initialDate; // 缓存获取到的初始日期 DayCountingBloc( RetrieveBeginDate retrieveBeginDate, StoreBeginDate storeBeginDate) : _retrieveBeginDate = retrieveBeginDate, _storeBeginDate = storeBeginDate, super(DayCountingInitial()) { on<DayCountingEvent>((event, emit) { emit(OnLoadingState()); }); on<RetrieveDateEvent>((event, emit) async { final res = await _retrieveBeginDate(NoParams()); _initialDate = res; emit(OnRetrieveSuccessState(date: res)); // 获取日期后启动每秒更新的定时器 _startUpdateTimer(emit); }); on<StoreDateEvent>((event, emit) async { final res = await _storeBeginDate(event.date); if (res) { _initialDate = event.date; emit(OnStoreSuccessState()); // 存储日期成功后启动定时器 _startUpdateTimer(emit); } else { emit(OnFailureState()); } }); } // 启动定时器,每秒计算时间差并发送状态 void _startUpdateTimer(Emitter<DayCountingState> emit) { // 先取消旧定时器,避免重复触发 _updateTimer?.cancel(); _updateTimer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_initialDate == null) return; final now = DateTime.now(); final difference = now.difference(_initialDate!); // 拆分时间差为天、时、分、秒 final totalSeconds = difference.inSeconds; final days = difference.inDays; final hours = difference.inHours % 24; final minutes = difference.inMinutes % 60; final seconds = difference.inSeconds % 60; // 发送更新状态 emit(OnTimerUpdateState( totalSeconds: totalSeconds, days: days, hours: hours, minutes: minutes, seconds: seconds, )); }); } // 关闭Bloc时销毁定时器,防止内存泄漏 @override Future<void> close() { _updateTimer?.cancel(); return super.close(); } }
3. UI层监听状态实时展示
在UI组件中监听OnTimerUpdateState,实时渲染计算出的流逝时长:
BlocBuilder<DayCountingBloc, DayCountingState>( builder: (context, state) { if (state is OnTimerUpdateState) { return Text( '已流逝: ${state.days}天 ${state.hours}时 ${state.minutes}分 ${state.seconds}秒', style: const TextStyle(fontSize: 18), ); } // 其他状态的UI处理逻辑 return const Text('加载中...'); }, )
关键注意点
- 每次启动定时器前先取消旧实例,避免多个定时器同时运行
- 必须在Bloc的
close方法中销毁定时器,防止内存泄漏 - 如果初始日期未获取到(比如首次打开还未存储),定时器不会执行计算,需先完成初始日期的存储逻辑
内容的提问来源于stack exchange,提问作者HaBuiDuc
相关产品推荐
相关产品推荐

