如何修复Flutter中Multiple widgets used the same GlobalKey错误?
修复Flutter中
Multiple widgets used the same GlobalKey错误 使用IntelliJ IDEA在安卓手机上运行Flutter项目,首次运行正常,但再次点击运行按钮时,日志出现Multiple widgets used the same GlobalKey错误,部分错误日志如下:
======== Exception caught by widgets library ======================================================= The following assertion was thrown while finalizing the widget tree: Multiple widgets used the same GlobalKey. The key [GlobalObjectKey int#371bd] was used by multiple widgets. The parents of those widgets were different widgets that both had the following description: IndexPage A GlobalKey can only be specified on one widget at a time in the widget tree. When the exception was thrown, this was the stack: #0 BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:3205:13) #1 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13) #2 BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure>.<anonymous closure> (package:flutter/src/widgets/framework.dart:3149:20) #3 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:633:13) #4 BuildOwner._debugVerifyGlobalKeyReservation.<anonymous closure> (package:flutter/src/widgets/framework.dart:3144:36) #5 BuildOwner._debugVerifyGlobalKeyReservation (package:flutter/src/widgets/framework.dart:3213:6) #6 BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:3267:11) #7 BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:3342:8) #8 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1169:19) #9 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:468:5) #10 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1397:15) #11 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1318:9) #12 SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:1040:9) #13 PlatformDispatcher.scheduleWarmUpFrame.<anonymous closure> (dart:ui/platform_dispatcher.dart:837:16) #17 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12) (elided 3 frames from class _Timer and dart:async-patch) ====================================================================================================
相关代码
路由代码:
final rootKey = GlobalKey<NavigatorState>(); final _shellKey = GlobalKey<NavigatorState>(debugLabel: "index"); @TypedShellRoute<IndexRoute>( routes: <TypedRoute<RouteData>>[ TypedGoRoute<FirstRoute>( path: "/", ), TypedGoRoute<SecondRoute>( path: "/second", ), ], ) class IndexRoute extends ShellRouteData { static final GlobalKey<NavigatorState> $navigatorKey = _shellKey; @override Widget builder(BuildContext context, GoRouterState state, Widget navigator) { return IndexPage(child: navigator); } } class FirstRoute extends GoRouteData { @override Page<void> buildPage(BuildContext context, GoRouterState state) { return const NoTransitionPage(child: FirstScreen()); } } class SecondRoute extends GoRouteData { @override Page<void> buildPage(BuildContext context, GoRouterState state) { return const NoTransitionPage(child: SecondScreen()); } }
主应用代码:
class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: GoRouter( initialLocation: "/", routes: $appRoutes, navigatorKey: rootKey, redirect: (context, state) { return null; }, ), ); } }
环境配置:
flutter doctor -v [✓] Flutter (Channel stable, 3.24.3, on macOS 14.6.1 23G93 darwin-arm64, locale zh-Hant-TW) • Flutter version 3.24.3 on channel stable at /Users/... • Upstream repository https://github.com/flutter/flutter.git • Framework revision 2663184aa7 (5 weeks ago), 2024-09-11 16:27:48 -0500 • Engine revision 36335019a8 • Dart version 3.5.3 • DevTools version 2.37.3 [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/... • Platform android-34, build-tools 34.0.0 • ANDROID_HOME = /Users/... • ANDROID_SDK_ROOT = /Users/... • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11609105) • All Android licenses accepted. [✓] IntelliJ IDEA Community Edition (version 2024.1.6) • IntelliJ at /Users/mosil/Applications/IntelliJ IDEA Community Edition 2024.1.6.app • Flutter plugin version 82.0.2 • Dart plugin version 241.18968.26 [✓] Connected device • Pixel 4 (mobile) • 98171FFAZ0038F • android-arm64 • Android 13 (API 33)
修复方案
错误日志明确指出冲突的Key属于IndexPage的实例,核心原因是**IndexPage内部使用了全局/静态的GlobalKey,热重载/再次运行时,旧的Widget树未完全销毁,新旧IndexPage实例共用同一个GlobalKey**。
按以下步骤修复:
1. 检查并修改IndexPage的Key使用
打开IndexPage的代码,确保它没有使用全局或静态的GlobalKey:
- 如果
IndexPage中定义了静态GlobalKey,直接删除该静态变量,改为使用Widget构造函数传入的key:
class IndexPage extends StatelessWidget { final Widget child; // 移除静态GlobalKey定义 const IndexPage({super.key, required this.child}); @override Widget build(BuildContext context) { return Scaffold( // 使用widget.key替代静态key key: widget.key, body: child, // 其他代码 ); } }
- 如果必须为
IndexPage指定GlobalKey,在创建IndexPage时每次生成新的实例:
修改IndexRoute的builder方法:
@override Widget builder(BuildContext context, GoRouterState state, Widget navigator) { // 每次创建IndexPage时生成新的GlobalKey return IndexPage( key: GlobalKey(), child: navigator, ); }
2. 优化全局NavigatorKey的生命周期(可选)
如果路由的全局rootKey和_shellKey也存在热重载冲突风险,可将它们从全局变量改为绑定到App的State中:
class App extends StatefulWidget { const App({super.key}); @override State<App> createState() => _AppState(); } class _AppState extends State<App> { final _rootKey = GlobalKey<NavigatorState>(); final _shellKey = GlobalKey<NavigatorState>(debugLabel: "index"); @override Widget build(BuildContext context) { return MaterialApp.router( routerConfig: GoRouter( initialLocation: "/", routes: $appRoutes, navigatorKey: _rootKey, redirect: (context, state) => null, ), ); } }
注:若使用此方式,需调整
IndexRoute中$navigatorKey的赋值逻辑,确保能访问到_shellKey(可通过单例、Provider等方式传递)。
验证修复
修改完成后,再次点击运行按钮,确认错误不再出现。
内容的提问来源于stack exchange,提问作者Ada
相关产品推荐
相关产品推荐

