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

Flutter定时跳转页面后导航失效问题排查与修复请求

注册完成页自动跳转后登录页导航失效问题解决

以下代码实现了注册完成后3秒自动跳转至LoginPage的功能,但跳转后LoginPage的导航功能失效,推测是Timer处理不当导致,希望在尽量少改动代码的前提下解决问题,并附带相关解释。

原代码

import 'package:flutter/material.dart';
import 'dart:async';
import 'login_page.dart';

class RegistrationCompleated extends StatefulWidget {
  const RegistrationCompleated({super.key});

  @override
  State<RegistrationCompleated> createState() => _RegistrationCompleatedState();
}

class _RegistrationCompleatedState extends State<RegistrationCompleated> {
  bool _move = false;
  int _remainingTime = 3;
  late Timer _timer;

  @override
  void initState() {
    _startTimer();

    super.initState();
  }

  void _startTimer() {
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        if (_remainingTime > 0) {
          _remainingTime--;
        } else {
          _timer.cancel();
          _move = true;
        }
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_move == true) {
      Navigator.push(
          context, MaterialPageRoute(builder: (context) => LoginPage()));
    }
    return WillPopScope(
      // 阻止系统返回键退出页面
      onWillPop: () async => false,
      child: Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: const Center(
            child: Text('Registration Finished'),
          ),
        ),
        body: Container(
          margin: const EdgeInsets.symmetric(horizontal: 25),
          alignment: Alignment.center,
          child: Text(
            'The registration was successful!!!\n You will be soon redirected to the login page.\n'
            'Please insert the new credentials in the login page to sign in.\n'
            'You will be redirect to the login page in $_remainingTime',
          ),
        ),
      ),
    );
  }
}

报错信息

I/flutter ( 6029): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 6029): The following assertion was thrown building RegistrationCompleated(dirty, state:
I/flutter ( 6029): _RegistrationCompleatedState#93bd2):
I/flutter ( 6029): setState() or markNeedsBuild() called during build.
I/flutter ( 6029): This Overlay widget cannot be marked as needing to build because the framework is already in the
I/flutter ( 6029): process of building widgets. A widget can be marked as needing to be built during the build phase
I/flutter ( 6029): only if one of its ancestors is currently building. This exception is allowed because the framework
I/flutter ( 6029): builds parent widgets before children, which means a dirty descendant will always be built.
I/flutter ( 6029): Otherwise, the framework might not visit this widget during this build phase.
I/flutter ( 6029): The widget on which setState() or markNeedsBuild() was called was:
I/flutter ( 6029):   Overlay-[LabeledGlobalKey<OverlayState>#4e841]
I/flutter ( 6029): The widget which was currently being built when the offending call was made was:
I/flutter ( 6029):   RegistrationCompleated
I/flutter ( 6029): 
I/flutter ( 6029): The relevant error-causing widget was:
I/flutter ( 6029):   RegistrationCompleated
I/flutter ( 6029):   RegistrationCompleated:file:///C:/flutterApp/login_page/lib/registration_page.dart:18:41
I/flutter ( 6029): 
I/flutter ( 6029): When the exception was thrown, this was the stack:
I/flutter ( 6029): #0      Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4651:9)
I/flutter ( 6029): #1      Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4663:6)
I/flutter ( 6029): #2      State.setState (package:flutter/src/widgets/framework.dart:1159:15)
I/flutter ( 6029): #3      OverlayState.rearrange (package:flutter/src/widgets/overlay.dart:640:5)
I/flutter ( 6029): #4      NavigatorState._flushHistoryUpdates (package:flutter/src/widgets/navigator.dart:4067:16)
I/flutter ( 6029): #5      NavigatorState._pushEntry (package:flutter/src/widgets/navigator.dart:4540:5)
I/flutter ( 6029): #6      NavigatorState.push (package:flutter/src/widgets/navigator.dart:4489:5)
I/flutter ( 6029): #7      Navigator.push (package:flutter/src/widgets/navigator.dart:2100:34)
I/flutter ( 6029): #8      _RegistrationCompleatedState.build (package:login_page/registration_compleated_page.dart:40:17)
I/flutter ( 6029): #9      StatefulElement.build (package:flutter/src/widgets/framework.dart:5198:27)
I/flutter ( 6029): #10     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5086:15)
I/flutter ( 6029): #11     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5251:11)
I/flutter ( 6029): #12     Element.rebuild (package:flutter/src/widgets/framework.dart:4805:7)
I/flutter ( 6029): #13     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2780:19)
I/flutter ( 6029): #14     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:903:21)
I/flutter ( 6029): #15     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:358:5)
I/flutter ( 6029): #16     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1289:15)
I/flutter ( 6029): #17     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1219:9)
I/flutter ( 6029): #18     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1077:5)
I/flutter ( 6029): #19     _invoke (dart:ui/hooks.dart:142:13)
I/flutter ( 6029): #20     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:359:5)
I/flutter ( 6029): #21     _drawFrame (dart:ui/hooks.dart:112:31)
I/flutter ( 6029): 
I/flutter ( 6029): ════════════════════════════════════════════════════════════════════════════════════════════════════
E/flutter ( 6029): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 2928 pos 18: '!navigator._debugLocked': is not true.
E/flutter ( 6029): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
E/flutter ( 6029): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
E/flutter ( 6029): #2      _RouteEntry.handlePush.<anonymous closure> (package:flutter/src/widgets/navigator.dart:2928:18)
E/flutter ( 6029): #3      TickerFuture.whenCompleteOrCancel.thunk (package:flutter/src/scheduler/ticker.dart:420:15)
E/flutter ( 6029): <asynchronous suspension>
E/flutter ( 6029): #4      TickerFuture.whenCompleteOrCancel.thunk (package:flutter/src/scheduler/ticker.dart:419:5)
E/flutter ( 6029): <asynchronous suspension>
E/flutter ( 6029): 
I/flutter ( 6029): Another exception was thrown: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4532 pos 12: '!_debugLocked': is not true.
I/chatty  ( 6029): uid=10124(com.example.login_page) 1.ui identical 6 lines
I/flutter ( 6029): Another exception was thrown: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 4532 pos 12: '!_debugLocked': is not true.

Flutter环境检测结果

PS C:\flutterApp\login_page> flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel master, 3.10.0-12.0.pre.26, on Microsoft Windows [Versione 10.0.19045.2846], locale it-IT)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2022 17.5.4)
[√] Android Studio (version 2022.2)
[√] VS Code (version 1.77.3)
[√] Connected device (4 available)
[√] Network resources

• No issues found!

问题根源

  1. 在build方法中执行导航操作:Flutter的build方法仅负责构建UI,在此方法中调用Navigator.push会触发框架的状态变更,而此时框架正处于构建流程中,会抛出setState() called during build和_debugLocked的错误,干扰导航栈的正常状态,导致后续LoginPage的导航功能失效。
  2. 重复触发导航:当_move设为true后,每次build都会执行一次Navigator.push,可能导致多次向导航栈中添加LoginPage,进一步破坏导航栈结构。

修改后的代码(改动极小)

import 'package:flutter/material.dart';
import 'dart:async';
import 'login_page.dart';

class RegistrationCompleated extends StatefulWidget {
  const RegistrationCompleated({super.key});

  @override
  State<RegistrationCompleated> createState() => _RegistrationCompleatedState();
}

class _RegistrationCompleatedState extends State<RegistrationCompleated> {
  int _remainingTime = 3;
  late Timer _timer;

  @override
  void initState() {
    _startTimer();
    super.initState();
  }

  void _startTimer() {
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        if (_remainingTime > 0) {
          _remainingTime--;
        } else {
          _timer.cancel();
          // 直接在定时器回调中执行导航,无需通过_move变量触发build
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => LoginPage()));
        }
      });
    });
  }

  // 添加dispose方法,页面销毁时取消定时器,避免内存泄漏
  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async => false,
      child: Scaffold(
        appBar: AppBar(
          automaticallyImplyLeading: false,
          title: const Center(
            child: Text('Registration Finished'),
          ),
        ),
        body: Container(
          margin: const EdgeInsets.symmetric(horizontal: 25),
          alignment: Alignment.center,
          child: Text(
            'The registration was successful!!!\n You will be soon redirected to the login page.\n'
            'Please insert the new credentials in the login page to sign in.\n'
            'You will be redirect to the login page in $_remainingTime',
          ),
        ),
      ),
    );
  }
}

关键改动解释

  1. 移除_move变量:不再通过状态变量触发导航,直接在定时器到期时执行跳转,避免不必要的UI重建和重复导航。
  2. 导航操作移至Timer回调:定时器到期后立即执行Navigator.push,此时Flutter不在构建流程中,不会触发锁错误,保证导航栈操作正常。
  3. 添加dispose方法:页面销毁时取消定时器,防止定时器在页面销毁后继续运行,引发内存泄漏或无效的上下文调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:48:11