Flutter Navigator.popUntil 断言 _debugLocked 失败。怎么了?

Flutter Navigator.popUntil failed assertion _debugLocked. What's wrong?

^^^^^^不!这个问题 没有答案! ^ ^ ^ ^ ^ ^

我在使用 Navigator.popUntil 时遇到问题。我写了一个小的演示应用程序来展示发生了什么。在我 post 这是一个错误之前,我使用 popUntil 是不是错了??

调用 popUntil 显示

似乎有什么东西锁定了 Navigator(设置 _debugLocked)而不释放它。

main.dart 下面:(可以直接粘贴到 Flutter 演示应用中)

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Routing Test Page'),
      onGenerateRoute: (RouteSettings settings) {
        switch (settings.name) {
          case '/':
            return MaterialPageRoute(
              builder: (_) => MyHomePage(title: 'Home Page',),
              settings: settings,
            );
          case '/home':
            return MaterialPageRoute(
              builder: (_) => MyHomePage(title: 'Home Page',),
              settings: settings,
            );
          case '/middlepage':
            return MaterialPageRoute(
              builder: (_) => MiddlePage(),
              settings: settings,
            );
          case '/bottompage':
            return MaterialPageRoute(
              builder: (_) => BottomBage(),
              settings: settings,
            );
          default:
            return null;
        }
      },
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Home Page',
            ),
            OutlineButton(
              child: Text('push MiddlePage()'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => (MiddlePage())),
              ),
            ),
            OutlineButton(
              child: Text('pushNamed ''/middlepage'''),
              onPressed: () => Navigator.pushNamed(context, '/middlepage'),
            ),
          ],
        ),
      ),
    );
  }
}

class MiddlePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Middle Page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Middle Page',style: TextStyle(fontWeight: FontWeight.bold)
            ),
            OutlineButton(
              child: Text('push BottomPage()'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => (BottomBage())),
              ),
            ),
            OutlineButton(
              child: Text('pushNamed ''/bottompage'''),
              onPressed: () => Navigator.pushNamed(context, '/bottompage'),
            ),
            OutlineButton(
                child: Text('pop'), onPressed: () => Navigator.pop(context)),
            OutlineButton(
                child: Text('popUntil ''/home'''),
                onPressed: () =>
                    Navigator.popUntil(context, ModalRoute.withName('/home'))),
          ],
        ),
      ),
    );
  }
}

class BottomBage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bottom page'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Bottom Page', style: TextStyle(fontWeight: FontWeight.bold),
            ),
            OutlineButton(
              child: Text('push ''home'''),
              onPressed: () =>
                  Navigator.pushNamed(context, '/home'),
            ),
            OutlineButton(
                child: Text('pop'),
                onPressed: () =>
                    Navigator.pop(context)),

            OutlineButton(
              child: Text('popUntil ''/home'''),
              onPressed: () =>
                  Navigator.popUntil(context, ModalRoute.withName('/home')),
            ),
            OutlineButton(
              child: Text('popUntil ''/home'' (with Are You Sure box)) '),
              onPressed: () async {
                try {
                  if (await _areYouSureDialog(context)) {
                    Navigator.popUntil(context, ModalRoute.withName('/home'));
                  }
                } catch (e) {
                  debugPrint("exception: $e");
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

Future<bool> _areYouSureDialog(BuildContext context) async {
  return await showDialog<bool>(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text('Pop back?'),
            content: const Text('Are you sure?'),
            actions: <Widget>[
              FlatButton(
                child: const Text('YES'),
                onPressed: () {
                  Navigator.of(context).pop(true);
                },
              ),
              FlatButton(
                child: const Text('NO'),
                onPressed: () {
                  Navigator.of(context).pop(false);
                },
              ),
            ],
          );
        },
      ) ??
      false;
}

我重新创建了你的案例。每当我们想从任何地方弹出导航到主屏幕(root)时,有两种方法可以做到这一点:

1.Using.isFirst方法:

Navigator.of(context).popUntil((route) => route.isFirst);
  1. 使用defaultRouteName

Navigator.popUntil(context, ModalRoute.withName(Navigator.defaultRouteName));

通过首先提供 contextroute 将确保导航始终弹出到默认设置。

您可以尝试任何一种方法。我最后测试了一下,效果很好。

希望这能回答您的问题。