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

Flutter禁用返回按钮时触发'!_debugLocked'错误的解决方法

Flutter PopScope 返回导航拦截报错:'!_debugLocked'断言失败解决

问题场景

需求:当_timerStarted或_isBrushing为true时,禁用页面的返回导航。

当前实现代码:

return PopScope(
    canPop: false,
    onPopInvokedWithResult: (didPop, result) async {
      // Allow pop only if the timer has finished or the user taps finishBrushing
      if (_timerStarted || _isBrushing) {
        // Show snackBar with 'Finish brushing to exit the screen'
        return; // Prevent exiting the screen by not invoking the pop
      }

      final navigator = Navigator.of(context);
      navigator.pop(result);
    },
    child: Scaffold(
    ...
    )
);

功能拦截正常,但允许返回退出时触发以下错误:

E/flutter ( 5204): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)]
Unhandled Exception: 'package:flutter/src/widgets/navigator.dart':
Failed assertion: line 5350 pos 12: '!_debugLocked': is not true.
E/flutter ( 5204): #0 _AssertionError._doThrowNew
(dart:core-patch/errors_patch.dart:50:61) E/flutter ( 5204): #1
_AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5) E/flutter ( 5204): #2 NavigatorState.pop
(package:flutter/src/widgets/navigator.dart:5350:12) E/flutter (
5204): #3 TimerScreenState.build.
(package:toothbrush/timer.dart:594:21) E/flutter ( 5204): #4
PopScope._callPopInvoked
(package:flutter/src/widgets/pop_scope.dart:137:30) E/flutter ( 5204):
#5 _PopScopeState.onPopInvokedWithResult (package:flutter/src/widgets/pop_scope.dart:172:12) E/flutter ( 5204):
#6 ModalRoute.onPopInvokedWithResult (package:flutter/src/widgets/routes.dart:1780:16) E/flutter ( 5204):
#7 _RouteEntry.handlePop (package:flutter/src/widgets/navigator.dart:3171:11) E/flutter (
5204): #8 NavigatorState._flushHistoryUpdates
(package:flutter/src/widgets/navigator.dart:4340:22) E/flutter (
5204): #9 NavigatorState.pop
(package:flutter/src/widgets/navigator.dart:5368:7) E/flutter ( 5204):
#10 TimerScreenState.build. (package:toothbrush/timer.dart:594:21) E/flutter ( 5204): #11
PopScope._callPopInvoked
(package:flutter/src/widgets/pop_scope.dart:137:30) E/flutter ( 5204):
#12 _PopScopeState.onPopInvokedWithResult (package:flutter/src/widgets/pop_scope.dart:172:12) E/flutter ( 5204):
#13 ModalRoute.onPopInvokedWithResult (package:flutter/src/widgets/routes.dart:1780:16) E/flutter ( 5204):
#14 NavigatorState.maybePop (package:flutter/src/widgets/navigator.dart:5319:25) E/flutter (
5204): E/flutter ( 5204): #15
WidgetsBinding.handlePopRoute
(package:flutter/src/widgets/binding.dart:848:11) E/flutter ( 5204):
E/flutter ( 5204): #16
MethodChannel._handleAsMethodCall
(package:flutter/src/services/platform_channel.dart:571:42) E/flutter
( 5204): E/flutter ( 5204): #17
_DefaultBinaryMessenger.setMessageHandler. (package:flutter/src/services/binding.dart:618:22) E/flutter ( 5204):
E/flutter ( 5204):

错误原因

核心问题在于错误组合使用PopScope的配置:

  1. 设置canPop: false后,导航框架已进入pop拦截流程,此时导航器处于锁定状态(_debugLocked为true)。
  2. 在onPopInvokedWithResult中手动调用navigator.pop(result),相当于在导航器的锁定流程中再次触发pop操作,触发框架的断言检查,导致报错。

修复方案

正确的做法是通过canPop属性直接控制是否允许返回,onPopInvokedWithResult仅处理拦截时的提示逻辑,无需手动调用pop:

  • 将canPop设置为!(_timerStarted || _isBrushing),当不需要拦截时,框架会自动处理返回操作。
  • 在onPopInvokedWithResult中,仅当需要拦截时执行提示(比如显示SnackBar)。

修复后代码示例

return PopScope(
  // 仅当不需要拦截时允许返回
  canPop: !(_timerStarted || _isBrushing),
  onPopInvokedWithResult: (didPop, result) {
    // didPop为false时,表示pop被拦截,此时显示提示
    if (!didPop && (_timerStarted || _isBrushing)) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Finish brushing to exit the screen')),
      );
    }
  },
  child: Scaffold(
    // 页面内容...
  ),
);

补充说明

  • didPop参数用于标识pop操作是否已被框架执行:canPop为true时,didPop为true,无需额外处理;canPop为false时,didPop为false,可执行拦截提示逻辑。
  • 这种写法符合PopScope的设计意图,避免了手动调用navigator.pop带来的状态冲突问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:12:05