Explorar o código

fix:修改定时器全局可以计时.

zhoukun hai 6 meses
pai
achega
97bf834c6b

+ 5 - 0
lib/data/repositories/member_repository.dart

@@ -5,6 +5,7 @@ import 'package:location/data/api/request/subscription_check_request.dart';
 import 'package:location/data/repositories/account_repository.dart';
 import 'package:location/utils/http_handler.dart';
 
+import '../../di/get_it.dart';
 import '../../utils/payment_status_manager.dart';
 import '../api/request/member_list_request.dart';
 import '../api/request/order_status_request.dart';
@@ -23,6 +24,10 @@ class MemberRepository {
 
   MemberRepository(this.atmobApi, this.accountRepository);
 
+  static MemberRepository getInstance() {
+    return getIt.get<MemberRepository>();
+  }
+
   Future<void> memberTrial() {
     return atmobApi
         .memberTrial(AppBaseRequest())

+ 116 - 0
lib/module/mine/mine_countdown_timer_manager.dart

@@ -0,0 +1,116 @@
+
+import 'dart:async';
+import 'package:flutter/foundation.dart';
+
+import '../../data/repositories/member_repository.dart';
+import '../member/member_page.dart';
+import 'mine_expiration_reminder_dialog.dart';
+
+/// 全局倒计时定时器管理器(单例模式)
+class MineCountdownTimerManager {
+  static final MineCountdownTimerManager _instance = MineCountdownTimerManager._internal();
+  factory MineCountdownTimerManager() => _instance;
+  MineCountdownTimerManager._internal();
+
+  // 存储所有倒计时任务
+  final Map<String, Timer> _timers = {};
+  final Map<String, StreamController<String>> _streamControllers = {};
+  final Map<String, Completer<void>> _completers = {};
+
+  /// 启动倒计时
+  Future<void> startCountdown({
+    required String key, // 倒计时唯一标识
+    required int endTimestamp, // 结束时间戳(毫秒)
+    required VoidCallback onExpired, // 过期回调
+  }) async {
+    // 取消已存在的同名倒计时
+    cancelCountdown(key);
+
+    // 创建过期回调的Completer
+    _completers[key] = Completer<void>();
+
+    // 计算剩余时间
+    DateTime endTime = DateTime.fromMillisecondsSinceEpoch(endTimestamp);
+    Duration remaining = endTime.difference(DateTime.now());
+
+    // 如果剩余时间小于等于0,直接触发过期回调
+    if (remaining.inSeconds <= 0) {
+      onExpired();
+      return;
+    }
+
+    // 创建StreamController用于通知UI更新
+    _streamControllers[key] = StreamController<String>.broadcast();
+
+    // 创建定时器
+    _timers[key] = Timer.periodic(Duration(seconds: 1), (timer) {
+      DateTime currentTime = DateTime.now();
+      Duration newRemaining = endTime.difference(currentTime);
+
+      if (newRemaining.inSeconds <= 0) {
+        // 倒计时结束
+        timer.cancel();
+        _timers.remove(key);
+        _streamControllers[key]?.close();
+        _streamControllers.remove(key);
+        onExpired();
+        _completers[key]?.complete();
+        _completers.remove(key);
+
+        ///弹出提示框
+        MemberRepository memberRepository = MemberRepository.getInstance();
+        memberRepository
+            .memberTrailInfo()
+            .then((infoRespons) {
+          MineExpirationReminderDialog.show(infoResponse: infoRespons,onDic: () {
+            MemberPage.start();
+          });
+          //MineExpirationReminderDialog.show(infoResponse: infoResponse);
+        }).catchError((){});
+      } else {
+        // 发送更新通知
+        String formattedTime = formatDuration(newRemaining);
+        _streamControllers[key]?.add(formattedTime);
+      }
+    });
+  }
+
+  /// 取消倒计时
+  void cancelCountdown(String key) {
+    _timers[key]?.cancel();
+    _timers.remove(key);
+    _streamControllers[key]?.close();
+    _streamControllers.remove(key);
+    _completers[key]?.complete();
+    _completers.remove(key);
+  }
+
+  /// 格式化时间
+  String formatDuration(Duration duration) {
+    String twoDigits(int n) => n.toString().padLeft(2, '0');
+    String hours = twoDigits(duration.inHours);
+    String minutes = twoDigits(duration.inMinutes.remainder(60));
+    String seconds = twoDigits(duration.inSeconds.remainder(60));
+    print("hourssfsdfsd---${seconds}");
+    return '$hours:$minutes:$seconds';
+  }
+
+  /// 获取倒计时流
+  Stream<String> getCountdownStream(String key) {
+    return _streamControllers[key]?.stream ?? Stream.empty();
+  }
+
+  /// 等待倒计时结束
+  Future<void> waitForCountdown(String key) {
+    return _completers[key]?.future ?? Future.value();
+  }
+
+  /// 清理所有倒计时
+  void dispose() {
+    _timers.forEach((key, timer) => timer.cancel());
+    _timers.clear();
+    _streamControllers.forEach((key, controller) => controller.close());
+    _streamControllers.clear();
+    _completers.clear();
+  }
+}

+ 75 - 106
lib/module/mine/mine_trial_membership_countdown_text.dart

@@ -1,4 +1,6 @@
 import 'dart:async';
+import 'package:flutter/foundation.dart';
+
 
 import 'package:flutter/material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
@@ -6,6 +8,7 @@ import 'package:location/utils/common_expand.dart';
 
 import '../../data/bean/member_status_info.dart';
 import '../../resource/string.gen.dart';
+import 'mine_countdown_timer_manager.dart'; // 导入全局定时器管理器
 
 class MineTrialMembershipCountdownText extends StatefulWidget {
   final MemberStatusInfo? memberStatusInfo;
@@ -14,7 +17,7 @@ class MineTrialMembershipCountdownText extends StatefulWidget {
   const MineTrialMembershipCountdownText({
     super.key,
     this.memberStatusInfo,
-    this.trialHasExpiredCallBack
+    this.trialHasExpiredCallBack,
   });
 
   @override
@@ -22,14 +25,15 @@ class MineTrialMembershipCountdownText extends StatefulWidget {
 }
 
 class _MineTrialMembershipCountdownTextState extends State<MineTrialMembershipCountdownText> {
-  Timer? _timer; // 使用可空类型,初始化为null
+  final MineCountdownTimerManager _timerManager = MineCountdownTimerManager();
   String _countdownText = '';
-  bool _isCountdownActive = false; // 标记倒计时是否活跃
+  late String _countdownKey; // 倒计时唯一标识
 
   @override
   void initState() {
     super.initState();
-    _initParameter();
+    _countdownKey = 'member_trial_countdown_${widget.memberStatusInfo?.hashCode ?? ''}';
+    _initCountdown();
   }
 
   @override
@@ -37,131 +41,96 @@ class _MineTrialMembershipCountdownTextState extends State<MineTrialMembershipCo
     super.didUpdateWidget(oldWidget);
     // 检查memberStatusInfo是否有变化
     if (widget.memberStatusInfo != oldWidget.memberStatusInfo) {
-
-      DateTime endTime = DateTime.fromMillisecondsSinceEpoch(widget.memberStatusInfo!.trialEndTimestamp ?? 0);
-      Duration remaining = endTime.difference(DateTime.now());
-      if (!_isCountdownActive) {
-        _resetTimer();
-        _initParameter();
-      }
+      _countdownKey = 'member_trial_countdown_${widget.memberStatusInfo?.hashCode ?? ''}';
+      _initCountdown();
     }
   }
 
-  void _initParameter() {
-    // 清除现有计时器
-    _resetTimer();
-
-    // 创建倒计时定时器
-    if (widget.memberStatusInfo?.trialed == true) {
-      // 计算剩余时间
-      DateTime endTime = DateTime.fromMillisecondsSinceEpoch(widget.memberStatusInfo!.trialEndTimestamp ?? 0);
-      Duration remaining = endTime.difference(DateTime.now());
-      if (remaining.inSeconds > 0) {
-        print("创建新的倒计时定时器");
-        // 创建每秒更新一次的定时器
-        _timer = Timer.periodic(const Duration(seconds: 1), (_) => _countdownisInProgress());
-        _isCountdownActive = true;
-        _updateTime();
-        _countdownisInProgress();
-      }  else {
-        _countdownText = StringName.memberTrialHasExpired;
-      }
-    } else {
-      // 将时间戳转换为DateTime(根据单位处理)
+  void _initCountdown() {
+    if (widget.memberStatusInfo == null) {
       _countdownText = StringName.memberExperienceVip;
+      return;
     }
-  }
 
-  void _resetTimer() {
-    // 取消现有计时器并重置状态
-    _timer?.cancel();
-    _timer = null;
-    _isCountdownActive = false;
-  }
+    if (widget.memberStatusInfo?.trialed != true) {
+      _countdownText = StringName.memberExperienceVip;
+      _timerManager.cancelCountdown(_countdownKey);
+      return;
+    }
 
-  void _updateTime() {
-    // 将时间戳转换为DateTime(根据单位处理)
-    _countdownText = StringName.memberExperienceVip;
-
-    if ((widget.memberStatusInfo?.trialed ?? false)) {
-      DateTime endTime = DateTime.fromMillisecondsSinceEpoch(widget.memberStatusInfo!.trialEndTimestamp ?? 0);
-      Duration remaining = endTime.difference(DateTime.now());
-      ///正在使用
-      if (remaining.inSeconds > 0) {
-        if (!_isCountdownActive) {
-          _countdownisInProgress();
-        }
-      } else {
-        //已经使用完了
-        _resetTimer();
-        _countdownText = StringName.memberTrialHasExpired;
-      }
-    } else {
-      // 未试用或其他状态
-      _resetTimer();
+    final timestamp = widget.memberStatusInfo!.trialEndTimestamp ?? 0;
+    if (timestamp == 0) {
+      _countdownText = StringName.memberTrialHasExpired;
+      _timerManager.cancelCountdown(_countdownKey);
+      return;
     }
-    setState(() {});
-  }
 
-  /// 正在倒计时
-  void _countdownisInProgress() {
-    // 检查时间戳是否为空
-    _countdownText = StringName.memberExperienceVip;
-    // 将时间戳转换为DateTime(根据单位处理)
-    final timestamp = widget.memberStatusInfo!.trialEndTimestamp!;
-    DateTime endTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
-    Duration remaining = endTime.difference(DateTime.now());
-    //print("倒计时状态---${widget.memberStatusInfo!.trialEndTimestamp}---:${remaining.inSeconds}---${remaining.inSeconds <= 0}---:${DateTime.now()}---:${endTime}");
-
-    if (widget.memberStatusInfo?.trialed == true) {
-        if (remaining.inSeconds == 0) {
-          _resetTimer(); // 取消计时器并重置状态
-          _countdownText = StringName.memberTrialHasExpired;
-          setState(() {});
-          if (widget.trialHasExpiredCallBack != null) {
-            widget.trialHasExpiredCallBack!();
-          }
-        } else {
-          //已经使用完了
-          _countdownText = _formatDuration(remaining);
-          _countdownText = '${StringName.memberCountdownRemaining} ${_countdownText} ${StringName.memberCountdownExperienceTime}';
-          if (mounted) {
-            setState(() {});
-          }
+    // 启动全局倒计时
+    _timerManager.startCountdown(
+      key: _countdownKey,
+      endTimestamp: timestamp,
+      onExpired: () {
+        if (mounted) {
+          setState(() {
+            _countdownText = StringName.memberTrialHasExpired;
+          });
         }
-    } else {
-      _resetTimer();
-      _countdownText = StringName.memberExperienceVip;
+      },
+    );
+
+    //widget.trialHasExpiredCallBack?.call();
+
+    // 订阅倒计时更新
+    _timerManager.getCountdownStream(_countdownKey).listen((formattedTime) {
       if (mounted) {
-        setState(() {});
+        setState(() {
+          _countdownText = '${StringName.memberCountdownRemaining} $formattedTime ${StringName.memberCountdownExperienceTime}';
+        });
       }
-    }
+    });
 
+    // 初始化时计算一次剩余时间
+    _updateInitialTime();
   }
 
-  String _formatDuration(Duration duration) {
-    String twoDigits(int n) => n.toString().padLeft(2, '0');
-    String hours = twoDigits(duration.inHours);
-    String minutes = twoDigits(duration.inMinutes.remainder(60));
-    String seconds = twoDigits(duration.inSeconds.remainder(60));
-    return '$hours:$minutes:$seconds';
+  void _updateInitialTime() {
+    if (widget.memberStatusInfo == null || widget.memberStatusInfo?.trialed != true) {
+      _countdownText = StringName.memberExperienceVip;
+      return;
+    }
+
+    final timestamp = widget.memberStatusInfo!.trialEndTimestamp ?? 0;
+    if (timestamp == 0) {
+      _countdownText = StringName.memberTrialHasExpired;
+      return;
+    }
+
+    DateTime endTime = DateTime.fromMillisecondsSinceEpoch(timestamp);
+    Duration remaining = endTime.difference(DateTime.now());
+
+    if (remaining.inSeconds > 0) {
+      String formattedTime = _timerManager.formatDuration(remaining);
+      _countdownText = '${StringName.memberCountdownRemaining} $formattedTime ${StringName.memberCountdownExperienceTime}';
+    } else {
+      _countdownText = StringName.memberTrialHasExpired;
+    }
   }
 
   @override
   void dispose() {
-    _resetTimer(); // 使用统一的方法清理计时器
+    //_timerManager.cancelCountdown(_countdownKey);
     super.dispose();
   }
 
   @override
   Widget build(BuildContext context) {
-    return  Text(
-        _countdownText,
-        style: TextStyle(
-            fontSize: 13.sp,
-            color: "#8A5F03".color,
-            fontWeight: FontWeight.bold
-        )
+    return Text(
+      _countdownText,
+      style: TextStyle(
+        fontSize: 13.sp,
+        color: "#8A5F03".color,
+        fontWeight: FontWeight.bold,
+      ),
     );
   }
-}
+}