使用persistent_bottom_nav_bar登出时触发Navigator断言异常求助
我使用persistent_bottom_nav_bar: ^5.0.2包构建多页面Flutter应用,每个页面的AppBar都设有登出按钮,点击登出时触发以下断言异常。
实现代码
class LoginPage extends StatefulWidget { const LoginPage({Key? key}) : super(key: key); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { GlobalKey<FormState> formKey = GlobalKey<FormState>(); @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( body: ListView( children: [ Form( key: formKey, child: Column( children: [ FloatingActionButton( onPressed: () async { if (formKey.currentState!.validate()) { if (accessToken != null) { Navigator.push( context, MaterialPageRoute( builder: (context) => MultiProvider( providers: [ ChangeNotifierProvider<DashboardProvider>( create: (context) => DashboardProvider()), ], child: Dashboard(), ), ), ); } } }, ), ], ), ), ], ), ), ); } } //////////////////////////////////////////////////////////////////////////////// class Dashboard extends StatefulWidget { Dashboard({Key? key}) : super(key: key); static PersistentTabController controller = PersistentTabController(initialIndex: 0); @override State<Dashboard> createState() => _DashboardState(); } class _DashboardState extends State<Dashboard> { List<Widget> _buildScreen() { return [ HomePage(), FoTotalOrdersLocation(), ]; } List<PersistentBottomNavBarItem> _navigationBarItems() { return [ PersistentBottomNavBarItem( icon: Icon( Icons.home, size: 30, ), textStyle: TextStyle(fontSize: 20), title: ("Home"), ), PersistentBottomNavBarItem( icon: Icon( Icons.location_on, size: 30, ), textStyle: TextStyle(fontSize: 20), title: ("Location"), ), ]; } @override void initState() { super.initState(); if (Dashboard.controller.index == 0) {} } @override Widget build(BuildContext context) { print("build called"); return Scaffold( body: ChangeNotifierProvider( create: (context) => FoHomePageProvider(context), child: PersistentTabView( context, controller: Dashboard.controller, screens: _buildScreen(), items: _navigationBarItems(), onItemSelected: (val) async {}, ), ), ); } } /////////////////////////////////////////////////////////////////////////////////////////// class HomePage extends StatelessWidget { const HomePage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( onPressed: () { Navigator.popUntil( context, ModalRoute.withName(' /loginPage'), ); }, icon: Icon(Icons.logout), ), ), body: ElevatedButtonWidget( text: "Next", onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => UsersPage(), ), ); }, ), ); } } /////////////////////////////////////////////////////////////////////////////////////////////////////////// import 'package:flutter/material.dart'; class UsersPage extends StatelessWidget { const UsersPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( leading: IconButton( onPressed: () { Navigator.popUntil( context, ModalRoute.withName(' /loginPage'), ); }, icon: Icon(Icons.logout), ), ), body: Text("Users page"), ); } }
异常信息
════════ Exception caught by widgets library ═══════════════════════════════════ 以下断言在构建Navigator(dirty, dependencies: [UnmanagedRestorationScope, HeroControllerScope], state: NavigatorState#5900b(tickers: tracking 0 tickers))时抛出: 'package:flutter/src/widgets/navigator.dart': 断言失败:第5140行第12位:'_history.isNotEmpty':不为真。 package:flutter/…/widgets/navigator.dart:5140 2
原因分析与修复方案
核心原因
- 路由名称匹配错误:你在
Navigator.popUntil中使用了带前置空格的' /loginPage',但登录页从未注册过这个路由名称,导致无法匹配到目标路由,最终触发栈为空的断言异常。 - 嵌套Navigator冲突:
PersistentTabView内部会创建独立的Navigator实例,子页面中调用的Navigator.popUntil操作的是这个内部Navigator,而非根Navigator。内部路由栈中不存在登录页,清空栈后就会触发_history.isNotEmpty断言失败。
修复步骤
1. 改用根Navigator执行登出操作
在所有登出按钮的点击逻辑中,指定使用根Navigator,并通过pushReplacement直接替换为登录页(避免栈操作异常):
// HomePage和UsersPage中的登出按钮逻辑替换为: onPressed: () { Navigator.of(context, rootNavigator: true).pushReplacement( MaterialPageRoute(builder: (context) => LoginPage()), ); },
2. 移除静态PersistentTabController
Dashboard中静态的PersistentTabController可能引发页面状态异常,改为在State中初始化:
class Dashboard extends StatefulWidget { Dashboard({Key? key}) : super(key: key); @override State<Dashboard> createState() => _DashboardState(); } class _DashboardState extends State<Dashboard> { late PersistentTabController _controller; @override void initState() { super.initState(); _controller = PersistentTabController(initialIndex: 0); } // 后续代码中用_controller替代Dashboard.controller }
3. 可选:使用命名路由优化跳转
如果项目规模较大,建议在MaterialApp中注册命名路由,进一步简化跳转逻辑:
MaterialApp( initialRoute: '/login', routes: { '/login': (context) => LoginPage(), '/dashboard': (context) => Dashboard(), }, ); // 登出逻辑可改为: Navigator.of(context, rootNavigator: true).pushReplacementNamed('/login');
内容的提问来源于stack exchange,提问作者Abdullah
相关产品推荐
相关产品推荐

