Ошибка, выдаваемая всплывающим навигатором, до тех пор, пока: "! _DebugLocked ': не соответствует действительности". - PullRequest
0 голосов
/ 10 апреля 2019

При появлении экрана, переходящего на другой экран путем нажатия на лист showBottomSheet, эта ошибка выдается через следующий код. Я не могу понять, почему это происходит.

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

Ошибка:

══╡ ИСКЛЮЧЕНИЕ ПРОВЕДЕНО БИБЛИОТЕКОЙ ВИДЖЕТОВ ═════════════════════ I / flutter (24830): следующее утверждение было сгенерировано при построении Navigator- [GlobalObjectKey I / flutter (24830): _WidgetsAppState # 90d1f] (грязный, состояние: NavigatorState # 6b2b6 (тикеры: отслеживание 1 тикера)): I / flutter (24830): 'package: flutter / src / widgets / navigator.dart': Неудачное утверждение: строка 1995 поз. 12: '! _DebugLocked': I / флаттер (24830): не соответствует действительности. I / flutter (24830): Либо утверждение указывает на ошибку в самой структуре, либо мы должны предоставить существенно I / flutter (24830): дополнительная информация в этом сообщении об ошибке, чтобы помочь вам определить и устранить основную причину. I / flutter (24830): В любом случае, пожалуйста, сообщите об этом утверждении, сообщив об ошибке на GitHub: I / флаттер (24830): https://github.com/flutter/flutter/issues/new?template=BUG.md I / flutter (24830): Когда было сгенерировано исключение, это был стек:

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Вместо того, чтобы дать вам прямой ответ, я расскажу вам, как я думал об этом, когда увидел вопрос, в надежде, что это поможет вам в будущем.

Давайтевзгляните на утверждение.Это говорит Failed assertion: line 1995 pos 12: '!_debugLocked': I/flutter (24830): is not true..Хм, интересно.Давайте посмотрим на эту строку кода.

assert(!_debugLocked);

Ну, это не дает мне больше информации, давайте посмотрим на переменную.

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

Это лучше.Он предназначен для предотвращения повторных входящих вызовов push, pop и т. Д. (Это означает, что он не хочет, чтобы вы вызывали «push», «pop» и т. Д. Из вызова «push», «pop»).Итак, давайте проследим это до вашего кода.

Это похоже на вероятного виновника:

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

Я собираюсь пропустить здесь шаг и использовать вместо этого дедуктивное рассуждение - я держу паричто закрытое будущее закончено в течение pop.Если хотите, подтвердите, прочитав код.

Итак, если проблема в том, что мы вызываем pop из функции pop, нам нужно найти способ отложить вызоввсплывать до тех пор, пока поп не завершится.

Это становится довольно простым - есть два способа сделать это.Простой способ состоит в том, чтобы просто использовать отложенное будущее с нулевой задержкой, при котором дарт будет планировать вызов как можно скорее, как только текущий стек вызовов вернется в цикл обработки событий:

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

Другой более трепетныйy способ сделать это - использовать планировщик для планирования вызова после завершения текущего цикла сборки / рендеринга:

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

Любой из этих способов должен устранить проблему, с которой вы столкнулись.

Однако возможен и другой вариант - в вашей ExtendedFloatingActionButton, где вы вызываете pop:

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

, вы могли бы вместо этого просто сделать вызов Navigator.of(context).popUntil....Это избавит от необходимости делать что-либо после вызова bottomSheet.closed.Однако, в зависимости от того, что еще вам может или не нужно делать в своей логике, это может быть не идеальным (я определенно вижу проблему с тем, что на нижнем листе показано изменение основной части страницы, и почему выпытался сделать это в логике страницы).

Кроме того, когда вы пишете свой код, я бы сильно рекомендовал разделить его на виджеты - например, нижний лист должен быть егособственный виджет.Чем больше у вас функций построения, тем сложнее им следовать, и это может фактически повлиять на производительность.Вы также должны избегать использования экземпляров GlobalKey везде, где это возможно - вы можете либо пропустить объекты (или обратные вызовы) вниз, если это только через несколько слоев, использовать шаблон .of (context) или использовать унаследованные виджеты.

0 голосов
/ 10 апреля 2019

Добавьте в свой класс это.

final GlobalKey<ScaffoldState> _globalKey = GlobalKey();
// ...

Scaffold(
  key: _globalKey,
  ...
)

Теперь, когда вы хотите вернуться назад, просто используйте это,

final bottomSheet = _globalKey.currentState.showBottomSheet(
      (context) {
    return Container(
      height: 72.0,
      child: FlatButton(
        child: Text("ORDER DETAILS"),
        onPressed: () {
          Navigator.of(context).pop();
        },
      ),
    );
  },
);
bottomSheet.closed.then((v) {
  Navigator.of(context)
      .popUntil((r) => r.settings.isInitialRoute);
});
...