导航器弹出错误,直到:“!_debugLocked":不正确." [英] Error thrown on navigator pop until : "!_debugLocked': is not true."

查看:22
本文介绍了导航器弹出错误,直到:“!_debugLocked":不正确."的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当通过单击 showBottomSheet 弹出导航到其他屏幕的屏幕时,通过以下代码抛出此错误.我不明白为什么会这样.

When popping a screen navigating to other one by clicking on the showBottomSheet, this error is thrown through the following code . I cant get why this is occurring.

class _CheckoutButtonState extends State<_CheckoutButton> {
  final GlobalKey<ScaffoldState> _globalKey = GlobalKey();
  final DateTime deliveryTime = DateTime.now().add(Duration(minutes: 30));

  final double deliveryPrice = 5.00;

  @override
  Widget build(BuildContext context) {
    SubscriptionService subscriptionService =
        Provider.of<SubscriptionService>(context);
    CheckoutService checkoutService = Provider.of<CheckoutService>(context);
    return Container(
      height: 48.0,
      width: MediaQuery.of(context).size.width * 0.75,
      child: StreamBuilder(
        stream: subscriptionService.subscription$,
        builder: (_, AsyncSnapshot<Subscription> snapshot) {
          if (!snapshot.hasData) {
            return Text("CHECKOUT");
          }
          final Subscription subscription = snapshot.data;
          final List<Order> orders = subscription.orders;
          final Package package = subscription.package;
          num discount = _getDiscount(package);
          num price = _totalPriceOf(orders, discount);
          return StreamBuilder<bool>(
              stream: checkoutService.loading$,
              initialData: false,
              builder: (context, snapshot) {
                bool loading = snapshot.data;
                return ExtendedFloatingActionButton(
                  loading: loading,
                  disabled: loading,
                  action: () async {
                    checkoutService.setLoadingStatus(true);
                    final subscription =
                        await Provider.of<SubscriptionService>(context)
                            .subscription$
                            .first;
                    try {
                      await CloudFunctions.instance.call(
                          functionName: 'createSubscription',
                          parameters: subscription.toJSON);
                      final bottomSheet =
                          _globalKey.currentState.showBottomSheet(
                        (context) {
                          return Container(
                            width: MediaQuery.of(context).size.width,
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                begin: Alignment.topCenter,
                                end: Alignment.bottomCenter,
                                colors: [
                                  Theme.of(context).scaffoldBackgroundColor,
                                  Theme.of(context).primaryColor,
                                  Theme.of(context).primaryColor,
                                ],
                                stops: [-1.0, 0.5, 1.0],
                              ),
                            ),
                            child: Column(
                              children: <Widget>[
                                Expanded(
                                  child: Column(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: <Widget>[
                                      Padding(
                                        padding:
                                            const EdgeInsets.only(bottom: 16.0),
                                        child: Text(
                                          "Thank you for your order",
                                          textAlign: TextAlign.center,
                                          style: Theme.of(context)
                                              .textTheme
                                              .display1,
                                        ),
                                      ),
                                      SvgPicture.asset(
                                        'assets/images/thumb.svg',
                                        height: 120.0,
                                        width: 100.0,
                                      )
                                      // CircleAvatar(
                                      // radius: 40.0,
                                      // backgroundColor: Colors.transparent,
                                      // child: Icon(
                                      // Icons.check,
                                      // color: Theme.of(context)
                                      // .textTheme
                                      // .display1
                                      // .color,
                                      // size: 80.0,
                                      // ),
                                      // ),
                                    ],
                                  ),
                                ),
                                Container(
                                  width:
                                      MediaQuery.of(context).size.width * 0.9,
                                  height: 72.0,
                                  padding: EdgeInsets.only(bottom: 24),
                                  child: ExtendedFloatingActionButton(
                                    text: "ORDER DETAILS",
                                    action: () {
                                      Navigator.of(context).pop();
                                    },
                                  ),
                                ),
                              ],
                            ),
                          );
                        },
                      );
                      bottomSheet.closed.then((v) {
                        Navigator.of(context)
                            .popUntil((r) => r.settings.isInitialRoute);
                      });
                    } catch (e) {
                      print(e);
                      final snackBar =
                          SnackBar(content: Text('Something went wrong!'));
                      Scaffold.of(context).showSnackBar(snackBar);
                    }
                  },
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text(
                        "CHECKOUT ",
                        style: Theme.of(context)
                            .textTheme
                            .display4
                            .copyWith(color: Colors.white),
                      ),
                      Text(
                        "EGP " +
                            (price + (orders.length * deliveryPrice))
                                .toStringAsFixed(2),
                        style: Theme.of(context)
                            .textTheme
                            .display4
                            .copyWith(color: Theme.of(context).primaryColor),
                      ),
                    ],
                  ),
                );
              });
        },
      ),
    );
  }

  num _totalPriceOf(List<Order> orders, num discount) {
    num price = 0;
    orders.forEach((Order order) {
      List<Product> products = order.products;
      products.forEach((Product product) {
        price = price + product.price;
      });
    });
    num priceAfterDiscount = price * (1 - (discount / 100));
    return priceAfterDiscount;
  }

  num _getDiscount(Package package) {
    if (package == null) {
      return 0;
    } else {
      return package.discount;
    }
  }
}

错误:

>══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (24830): The following assertion was thrown building Navigator-[GlobalObjectKey<NavigatorState>
I/flutter (24830): _WidgetsAppState#90d1f](dirty, state: NavigatorState#6b2b6(tickers: tracking 1 ticker)):
I/flutter (24830): 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 1995 pos 12: '!_debugLocked':
I/flutter (24830): is not true.
I/flutter (24830): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter (24830): more information in this error message to help you determine and fix the underlying cause.
I/flutter (24830): In either case, please report this assertion by filing a bug on GitHub:
I/flutter (24830):   https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter (24830): When the exception was thrown, this was the stack:

推荐答案

我不会直接给你答案,而是会带你了解我看到这个问题时的想法,希望它'将来会帮助你.

Instead of giving you a direct answer, I'm going to walk you through how I thought about this when I saw the question, in the hope that it'll help you in the future.

让我们来看看断言.它说 Failed assertion: line 1995 pos 12: '!_debugLocked': I/flutter (24830): is not true..嗯,有意思.我们来看看那行代码.

Let's take a look at the assertion. It says Failed assertion: line 1995 pos 12: '!_debugLocked': I/flutter (24830): is not true.. Hmm, interesting. Let's take a look at that line of code.

assert(!_debugLocked);

好吧,这并没有给我更多信息,让我们看看变量.

Well, that doesn't give me much more information, let's look at the variable.

bool _debugLocked = false;//用于防止重入调用push、pop和friends

这样更好.它用于防止对 push、pop 等的重入调用(这意味着它不希望您在对 'push'、'pop' 的调用中调用 'push'、'pop' 等).因此,让我们将其追溯到您的代码.

That's better. It's there to prevent re-entrant calls to push, pop, etc (by that it means that it doesn't want you calling 'push', 'pop', etc from within a call to 'push', 'pop'). So let's trace that back to your code.

这似乎是罪魁祸首:

bottomSheet.closed.then((v) {
  Navigator.of(context)
    .popUntil((r) => r.settings.isInitialRoute);
});

我将在这里跳过一个步骤,而是使用演绎推理 - 我打赌封闭的未来在 pop 期间结束.如果您愿意,请继续阅读代码以确认这一点.

I'm going to skip a step here and use deductive reasoning instead - I'm betting that the closed future is finished during a pop. Go ahead and confirm that by reading the code if you feel like it.

因此,如果问题是我们在 pop 函数中调用 pop,我们需要想办法将调用推迟到 pop 完成之后.

So, if the issue is that we're calling pop from within a pop function, we need to figure out a way to defer the call to pop until after the pop has completed.

这变得非常简单 - 有两种方法可以做到这一点.简单的方法是使用零延迟的延迟未来,一旦当前调用堆栈返回到事件循环,它就会尽快安排调用:

This becomes quite simple - there's two ways to do this. The simple way is to just use a delayed future with zero delay, which will have dart schedule the call as soon as possible once the current call stack returns to the event loop:

Future.delayed(Duration.zero, () {
  Navigator. ...
});

另一种更流畅的方法是使用调度程序在当前构建/渲染周期完成后安排调用:

The other more flutter-y way of doing it would be to use the Scheduler to schedule a call for after the current build/render cycle is done:

SchedulerBinding.instance.addPostFrameCallback((_) {
  Navigator. ...
});

无论哪种方式都可以消除您遇到的问题.

Either way should eliminate the problem you're having.

另一个选项也是可能的 - 在你调用 pop 的 ExtendedFloatingActionButton 中:

Another option is also possible though - in your ExtendedFloatingActionButton where you call pop:

ExtendedFloatingActionButton(
 text: "ORDER DETAILS",
  action: () {
    Navigator.of(context).pop();
  },
),

您可以改为简单地调用 Navigator.of(context).popUntil....这将消除在调用 bottomSheet.closed 之后做任何事情的需要.但是,根据您在逻辑中可能需要或不需要做的任何其他事情,这可能并不理想(我绝对可以看到让底部工作表引发对页面主要部分的更改的问题以及您为什么试图在页面的逻辑中实现这一点).

you could instead simply do the call to Navigator.of(context).popUntil.... That would eliminate the need for the doing anything after bottomSheet.closed is called. However, depending on whatever else you might or might not need to do in your logic this may not be ideal (I can definitely see the issue with having the bottom sheet set off a change to the main part of the page and why you've tried to make that happen in the page's logic).

此外,当您编写代码时,我强烈建议将其分成小部件 - 例如,底部工作表应该是它自己的小部件.您在构建函数中拥有的越多,就越难遵循,它实际上也会对性能产生影响.您还应该尽可能避免使用 GlobalKey 实例 - 如果仅通过几层,您通常可以向下传递对象(或回调)、使用 .of(context) 模式或使用继承的小部件.

Also, when you're writing your code I'd highly recommend separating it into widgets - for example the bottom sheet should be its own widget. The more you have in a build function, the harder it is to follow and it can actually have an effect on performance as well. You should also avoid using GlobalKey instances wherever possible - you can generally either pass objects (or callbacks) down if it's only through a few layers, use the .of(context) pattern, or use inherited widgets.

这篇关于导航器弹出错误,直到:“!_debugLocked":不正确."的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆