import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:location/resource/colors.gen.dart'; import 'package:location/utils/common_expand.dart'; import 'dart:async'; import '../../utils/mmkv_util.dart'; final String MemberDiscountCountdownTimeCount = 'key_member_discount_countdown_time_count'; class MemberDiscountCountdownWidget extends StatefulWidget { final Duration duration; // 倒计时总时长(默认1小时) final TextStyle? textStyle; final Duration animationDuration; final Widget? placeholder; final Widget? expiredWidget; // 已过期时显示的组件 final VoidCallback? onExpired; // 倒计时结束回调 const MemberDiscountCountdownWidget({ Key? key, this.duration = const Duration(hours: 1), this.textStyle, this.animationDuration = const Duration(milliseconds: 500), this.placeholder, this.expiredWidget, this.onExpired, }) : super(key: key); @override _MemberDiscountCountdownWidgetState createState() => _MemberDiscountCountdownWidgetState(); } class _MemberDiscountCountdownWidgetState extends State with SingleTickerProviderStateMixin { // 1. 将_timer改为可空类型,移除late Timer? _timer; bool _isVisible = true; bool _isExpired = false; DateTime? _startTime; Duration? _remainingDuration; bool _isLoading = true; @override void initState() { super.initState(); _loadStartTime(); } Future _loadStartTime() async { try { final savedTime = KVUtil.getInt(MemberDiscountCountdownTimeCount, 0); print("savetimefdifjd---${savedTime}"); if (savedTime != null && savedTime > 0) { _startTime = DateTime.fromMillisecondsSinceEpoch(savedTime); _updateRemainingTime(); if (_remainingDuration != null && _remainingDuration!.isNegative) { _handleExpired(); } else { _startTimer(); } } else { _startNewCountdown(); } } catch (e) { print("加载倒计时时间出错: $e"); // 异常时调用修复后的_handleExpiredOver _handleExpiredOver(); } finally { if (mounted) { setState(() { _isLoading = false; }); } } } void _startNewCountdown() { _startTime = DateTime.now(); _saveStartTime(); _updateRemainingTime(); _startTimer(); } Future _saveStartTime() async { try { KVUtil.putInt(MemberDiscountCountdownTimeCount, _startTime!.millisecondsSinceEpoch); } catch (e) { print("保存倒计时时间出错: $e"); } } void _startTimer() { // 2. 先取消可能存在的旧定时器(避免重复创建) _timer?.cancel(); // 3. 重新创建定时器并赋值 _timer = Timer.periodic(Duration(seconds: 1), (timer) { if (mounted) { setState(() { _updateRemainingTime(); if (_remainingDuration != null && _remainingDuration!.isNegative) { _handleExpired(); } }); } }); } void _updateRemainingTime() { if (_startTime == null) return; final now = DateTime.now(); final endTime = _startTime!.add(widget.duration); _remainingDuration = endTime.difference(now); } void _handleExpired() { // 4. 安全取消定时器(允许_timer为null) _timer?.cancel(); _isExpired = true; if (mounted) { widget.onExpired?.call(); } } void _handleExpiredOver() { // 5. 修复这里!使用?避免对null调用cancel() _timer?.cancel(); _isExpired = true; widget.onExpired?.call(); } @override void dispose() { // 6. 销毁时安全取消 _timer?.cancel(); super.dispose(); } // 以下代码不变... String _formatDuration(Duration duration) { final hours = duration.inHours; final minutes = duration.inMinutes.remainder(60); final seconds = duration.inSeconds.remainder(60); return '${hours.toString().padLeft(2, '0')} : ' '${minutes.toString().padLeft(2, '0')} : ' '${seconds.toString().padLeft(2, '0')}'; } @override Widget build(BuildContext context) { if (_isLoading) { return const CircularProgressIndicator(); } if (_isExpired) { return widget.expiredWidget ?? const SizedBox.shrink(); } if (!_isVisible) { return widget.placeholder ?? const SizedBox.shrink(); } if (_remainingDuration == null || _remainingDuration!.isNegative) { return _createCellWidget("00","00","00"); } final hours = _remainingDuration!.inHours; final minutes = _remainingDuration!.inMinutes.remainder(60); final seconds = _remainingDuration!.inSeconds.remainder(60); final hoursStr = hours.toString().padLeft(2, '0'); final minutesStr = minutes.toString().padLeft(2, '0'); final secondsStr = seconds.toString().padLeft(2, '0'); return _createCellWidget(hoursStr, minutesStr, secondsStr); } Widget _createCellWidget(String hoursStr, String minutesStr, String secondsStr) { return Container( child: Row( children: [ Text( "优惠限时", style: TextStyle( color: "#333333".color, fontSize: 11.sp, fontWeight: FontWeight.w700), ), SizedBox(width: 5.w), _createItemWidget(hoursStr), _createItemMidele(), _createItemWidget(minutesStr), _createItemMidele(), _createItemWidget(secondsStr), ], ), ); } Widget _createItemWidget(String timeStr) { return Container( height: 15.w, // 确保容器有足够高度 alignment: Alignment.center, decoration: BoxDecoration( borderRadius: BorderRadius.circular(3), color: "#8B79F3".color, ), padding: EdgeInsets.symmetric(horizontal: 2.w), child: Text( timeStr, style: TextStyle( fontSize: 11.sp, color: ColorName.white, fontWeight: FontWeight.w500, ), ), ); } Widget _createItemMidele() { return Container( alignment: Alignment.center, width: 4.w, child: Center( child: Text( ":", style: TextStyle( fontSize: 11.sp, color: "#8B79F3".color, fontWeight: FontWeight.w400)), ), ); } }