Flutter Web使用go_router重载报Cannot set URL strategy more than once错误
问题产生原因
你将GoRouter实例的初始化逻辑写在了StatelessWidget的build方法中。Flutter框架在页面重载、热重载、组件树重绘时,会反复执行build方法,每次执行都会生成全新的GoRouter实例。当你给GoRouter配置了urlPathStrategy: UrlPathStrategy.path时,实例初始化阶段会调用Flutter Web的全局URL策略设置接口,而这个接口有全局校验,整个应用生命周期内只允许设置一次URL策略,重复调用就会抛出你看到的:
Assertion failed: org-dartlang-sdk:///flutter_web_sdk/lib/_engine/engine/window.dart:25:10
!_isUrlStrategySet
"Cannot set URL strategy more than once."
首次加载页面时build仅执行一次,路由初始化正常,所以返回按钮功能可以正常运行;一旦触发页面重载,build再次执行就会重复初始化路由触发报错。
修复方案
两种修复方式二选一即可,核心原则是保证GoRouter实例和URL策略配置全局仅执行一次,不要放在build生命周期内。
- 方案1:调整现有代码结构,将
GoRouter实例从build方法中提取为类的静态常量/成员,不会随build执行重复创建。
修改后的完整代码示例:
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:navigator_2/some_app.dart'; import 'details_page.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // 路由实例作为类静态属性,全局仅初始化一次 static final GoRouter _router = GoRouter( urlPathStrategy: UrlPathStrategy.path, routes: [ GoRoute(path: '/',builder: (context,state)=> const SomeAppPage()), GoRoute(path: '/details',builder: (context,state){ final query = state.queryParams['index']; return DetailsPage(index: int.parse(query!)); }), ], ); @override Widget build(BuildContext context) { return MaterialApp.router( routeInformationParser: _router.routeInformationParser, routerDelegate: _router.routerDelegate , title: 'Go Router Example', theme: ThemeData( primarySwatch: Colors.blue, ), ); } }
- 方案2:如果你使用的是go_router 5.0及以上的新版本,官方已经废弃了GoRouter构造函数中的
urlPathStrategy入参,要求在main函数中runApp调用前全局配置一次URL策略,从写法上避免重复设置的问题。
对应代码示例:
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:navigator_2/some_app.dart'; import 'details_page.dart'; void main() { // Web环境下全局仅调用一次URL策略配置,写在runApp之前 if (kIsWeb) { GoRouter.setUrlPathStrategy(UrlPathStrategy.path); } runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); static final GoRouter _router = GoRouter( // 新版本移除了构造函数内的urlPathStrategy配置项 routes: [ GoRoute(path: '/',builder: (context,state)=> const SomeAppPage()), GoRoute(path: '/details',builder: (context,state){ final query = state.queryParams['index']; return DetailsPage(index: int.parse(query!)); }), ], ); @override Widget build(BuildContext context) { return MaterialApp.router( routeInformationParser: _router.routeInformationParser, routerDelegate: _router.routerDelegate , title: 'Go Router Example', theme: ThemeData( primarySwatch: Colors.blue, ), ); } }
注意:不要将路由实例放在build方法内创建,除了触发本次的URL策略报错,还可能导致路由状态丢失、不必要的性能损耗。
内容的提问来源于stack exchange,提问作者Divyam Makar
相关产品推荐
相关产品推荐

