web-dev-qa-db-fra.com

Erreur lancée sur le navigateur pop jusqu'à ce que: "! _DebugLocked ': n'est pas vrai."

Lorsque vous sautez un écran en naviguant vers un autre en cliquant sur le showBottomSheet, cette erreur est générée par le code suivant. Je ne peux pas comprendre pourquoi cela se produit.

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

Erreur :

══╡ EXCEPTION PRISE PAR LA BIBLIOTHÈQUE WIDGETS ╞═════════════════════════════════════════ ══════════════════ I/flutter (24830): l'assertion suivante a été lancée en construisant Navigator- [GlobalObjectKey I/flutter (24830): _WidgetsAppState # 90d1f] (sale, état : NavigatorState # 6b2b6 (tickers: tracking 1 ticker)): I/flutter (24830): 'package: flutter/src/widgets/navigator.Dart': Échec de l'assertion: ligne 1995 pos 12: '! _DebugLocked': I/flutter (24830): n'est pas vrai. I/flutter (24830): Soit l'assertion indique une erreur dans le framework lui-même, soit nous devons fournir sensiblement I/flutter (24830): plus d'informations dans ce message d'erreur pour vous aider à déterminer et corriger la cause sous-jacente. I/flutter (24830): Dans les deux cas, veuillez signaler cette assertion en signalant un bug sur GitHub: I/flutter (24830): https://github.com/flutter/flutter/issues/new?template = BUG.md I/flutter (24830): Lorsque l'exception a été levée, c'était la pile:

8
Aya Elsisy

Au lieu de vous donner une réponse directe, je vais vous expliquer comment j'y ai pensé quand j'ai vu la question, dans l'espoir que cela vous aidera à l'avenir.

Jetons un coup d'œil à l'assertion. Il dit Failed assertion: line 1995 pos 12: '!_debugLocked': I/flutter (24830): is not true.. Hum ... intéressant. Jetons un coup d'œil à cette ligne de code.

assert(!_debugLocked);

Eh bien, cela ne me donne pas beaucoup plus d'informations, regardons la variable.

bool _debugLocked = false; // used to prevent re-entrant calls to Push, pop, and friends

C'est mieux. Il est là pour empêcher les appels entrants vers Push, pop, etc. (cela signifie qu'il ne veut pas que vous appeliez 'Push', 'pop', etc. depuis un appel à 'Push', 'pop'). Alors, remontons à votre code.

Cela semble être le coupable probable:

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

Je vais sauter une étape ici et utiliser un raisonnement déductif à la place - je parie que l'avenir fermé est terminé pendant un pop. Allez-y et confirmez cela en lisant le code si vous en avez envie.

Donc, si le problème est que nous appelons pop depuis une fonction pop, nous devons trouver un moyen de reporter l'appel à pop jusqu'à ce que la pop soit terminée.

Cela devient assez simple - il y a deux façons de procéder. Le moyen le plus simple consiste à simplement utiliser un futur retardé avec zéro retard, ce qui aura pour effet que Dart planifie l'appel dès que possible une fois que la pile d'appels actuelle revient dans la boucle d'événements:

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

L'autre façon plus simple de le faire serait d'utiliser le Planificateur pour planifier un appel après la fin du cycle de génération/rendu actuel:

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

Dans les deux cas, vous devez éliminer le problème que vous rencontrez.

Une autre option est également possible - dans votre ExtendedFloatingActionButton où vous appelez pop:

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

à la place, vous pouvez simplement appeler Navigator.of(context).popUntil.... Cela éliminerait le besoin de faire quoi que ce soit après l'appel de bottomSheet.closed. Cependant, selon tout ce que vous pourriez ou ne devriez pas faire dans votre logique, cela peut ne pas être idéal (je peux certainement voir le problème avec le fait que la feuille du bas déclenche un changement dans la partie principale de la page et pourquoi vous avez essayé de faire que cela se produise dans la logique de la page).

De plus, lorsque vous écrivez votre code, je fortement recommande de le séparer en widgets - par exemple, la feuille du bas devrait être son propre widget. Plus vous en avez dans une fonction de construction, plus elle est difficile à suivre et peut également avoir un effet sur les performances. Vous devez également éviter d'utiliser des instances GlobalKey dans la mesure du possible - vous pouvez généralement passer des objets (ou des rappels) vers le bas si ce n'est que sur quelques couches, utiliser le modèle .of (context) ou utiliser des widgets hérités.

32
rmtmckenzie