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

查看:81
本文介绍了在导航器弹出窗口上引发错误,直到:“!_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;
    }
  }
}

错误:


══╡小工具库的例外查询╞═══════════════════ b
I /颤振(24830) :引发了以下断言,以构建Navigator- [GlobalObjectKey
I / flutter(24830):_WidgetsAppState#90d1f](脏,状态:NavigatorState#6b2b6(tickers:跟踪1个股票)):
I / flutter (24830):'package:flutter / src / widgets / navigator.dart':失败的断言:第1995行pos 12:'!_debugLocked':
I / flutter(24830):不正确。
I / flutter(24830):或者断言表明框架本身有错误,或者我们应该提供大量的
I / flutter(24830):此错误消息中的更多信息可帮助您确定和修复根本原因。
I / flutter(24830):无论哪种情况,请通过在GitHub上提交错误来报告此断言:
I / flutter(24830): https://github.com/flutter/flutter/issues/new?template=BUG.md
我/ flutter(24830):引发异常时,这是堆栈:

══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ I/flutter (24830): The following assertion was thrown building Navigator-[GlobalObjectKey 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):不正确。。嗯,有趣。

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; //用来防止再次进入推入,弹出和好友调用

它可以防止再次进入推送,弹出等调用(这意味着它不希望您在推送,弹出的调用中调用推送,弹出等)。因此,让我们将其追溯到您的代码。

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);
});

我将在这里跳过步骤,而是使用演绎推理-我敢打赌, 流行结束了封闭的未来。

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,我们需要找出一种方法,可以将对弹出窗口的调用推迟到弹出窗口完成之后。

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.

这变得非常简单-有两种方法可以执行此操作。简单的方法是仅使用零延迟的延迟未来,一旦当前调用堆栈返回到事件循环,dart将尽快安排调用:

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.

虽然也可以使用另一个选项-在ExtendedPloatingActionButton中调用pop的位置:

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天全站免登陆