You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何在Widget #1启动的定时器无法在Widget #2中持续运行?

Flutter Provider全局登录状态定时校验仅执行一次问题修复

我使用provider实现了GlobalsProvider类管理全局变量,核心是维护用户登录状态:包含loggedIn布尔变量,以及每10秒调用SQL Server存储过程校验登录有效性的定时任务。之前在login.dart中运行正常,移至全局Provider后,定时任务仅执行一次,未按10秒间隔触发,已通过打印日志确认该问题。

相关代码

GlobalsProvider

Timer? timer;

void startLoginStream(/*...parms...*/) {
    timer = Timer.periodic(const Duration(seconds: 10), (Timer t) => loginStream(/*...parms...*/);

    notifyListeners();
}

void loginStream(/*...parms...*/) async {
        final previousLoggedIn = loggedIn;
    
        await sqlConnect(/*...parms...*/);
    
        var res = await SqlConn.readData("exec spHandheldLogin");
    
        res = json.decode(res);
        res = res[0]; //存储过程只会返回一行数据,取第一个元素无问题
        var loginState = res['LoginState'];
    
        if (kDebugMode) {print('${StaticGlobals.tagATS} loginStream loginState: ${loginState.toString()}');}
    
        if (loginState == 1) {
          loggedIn = true;
          loggedInUser = username;
        } else {
          loggedIn = false;
          loggedInUser = '';
        }
    
        await sqlDisconnect();
    
        //仅登录状态变化时通知监听者
        if (loggedIn != previousLoggedIn) {
          notifyListeners();
        }
    }

login.dart

@override
  Widget build(BuildContext context) {
    return Consumer<GlobalsProvider>(
        builder: (context, value, child) => Scaffold(appBar: AppBar(
              title: const Text('Login'),
            ),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                   Expanded(
                    child: TextButton(
                      onPressed: () async {
                        final status = await value.login(/*...parms...*/);

                        if (value.loggedIn == true) { //登录成功后启动定时校验
                          value.loginStream(/*...parms...*/);
                        } else {
                          Fluttertoast.showToast(
                              msg: "ERROR",
                              toastLength: Toast.LENGTH_LONG,
                          );
                        }
                      },
                      child: const Text('Submit'),
                    ),
                  )
                  //...

wrapper.dart

class Wrapper extends StatelessWidget {
  const Wrapper({super.key});

  @override
  Widget build(BuildContext context) {
    return Consumer<GlobalsProvider>(builder: (context, value, child) {
      if (value.loggedIn == true) {
        return const Forms(); //登录后页面
      } else {
        return const Login(); //登录页
      }
    });
  }
}

问题原因与修复方案

  1. 核心问题:登录成功后调用的是单次执行的loginStream(),而非启动定时任务的startLoginStream(),导致仅执行一次校验,未触发周期性定时器。
  2. 修复步骤:
    • 修改login.dart中登录成功分支的代码,将value.loginStream(/*...parms...*/)替换为value.startLoginStream(/*...parms...*/),启动真正的周期性任务。
    • 优化startLoginStream方法,添加定时器判空取消逻辑,避免重复创建定时器:
      void startLoginStream(/*...parms...*/) {
          //先取消已有定时器,防止重复创建
          timer?.cancel();
          timer = Timer.periodic(const Duration(seconds: 10), (Timer t) => loginStream(/*...parms...*/));
          notifyListeners();
      }
      
    • 添加资源清理逻辑,在Provider销毁时取消定时器,避免内存泄漏:
      @override
      void dispose() {
        timer?.cancel();
        super.dispose();
      }
      

内容的提问来源于stack exchange,提问作者TheMortiestMorty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:17:18