Использование индекса значения списка, хранящегося в переменной, вызывает ошибку, при использовании значения списка напрямую работает нормально Flutter - PullRequest
0 голосов
/ 16 июня 2020

На моем экране на половине экрана отображается ListView, который показывает все записи бронирования из локальной базы данных, которые сохраняются в List<Booking> bookings, на другой половине у меня есть подробное представление для выбранного элемента бронирования из ListView . В подробном представлении у меня также есть 3 кнопки, которые отправляют событие уведомления pu sh в blo c, которое принимает бронирование в качестве входного параметра. Чтобы иметь возможность иметь ссылку на Booking, отображаемую в подробном представлении, я сохраняю индекс элемента ListView в переменной int selectedBooking = 0; при выборе элемента из ListView. Проблема в том, что отправка события уведомления с помощью кнопок, использующих эту переменную, вызывает ошибку. Я попытался отправить его прямо из выбора элемента ListView, и он был отправлен нормально. Я уверен, что это не null, поскольку я печатаю bookings[selectedBooking] перед отправкой уведомления и печатаю нормально, но каким-то образом событие отправки уведомления вызывает ошибку, которая не печатается в области catch.

Единственное отличие состоит в том, что в onTap: элемента ListView я принимаю бронирование напрямую, это List<Booking> с booking[index], а в onPressed: кнопки я использую переменную, которая хранит тот же индекс bookings[selectedBooking] ..

Это экранная сборка:

Widget build(BuildContext context) {
    return MultiBlocProvider(
        providers: [
          BlocProvider<BookingBloc>(
            create: (context) =>
                BookingBloc(widget.user)..add(LoadBookings(user: widget.user)),
          ),
          BlocProvider<PushNotificationBloc>(
            create: (context) => PushNotificationBloc(),
          ),
        ],
        child: MultiBlocListener(
          listeners: [
            BlocListener<BookingBloc, BookingState>(
                listener: (BuildContext context, BookingState state) {
              if (state is LoadedBookings) {
                setState(() {
                  bookings = state.bookings;
//                  isSelected = state.isSelected;
//                  Timer(Duration(milliseconds: 50), () {
//                    scrollToIndex(bookings);
//                  });
                });
              }
              if (state is BookingDetails) {
                setState(() {
                  bookingId = state.booking.bookingId;
                  bookingDate = dateOnlyFormat.format(
                      DateTime.fromMillisecondsSinceEpoch(
                          state.booking.bookingStart));
                  bookingStart = timeFormat.format(
                      DateTime.fromMillisecondsSinceEpoch(
                          state.booking.bookingStart));
                  bookingEnd = timeFormat.format(
                      DateTime.fromMillisecondsSinceEpoch(
                          state.booking.bookingEnd));
                  customerName = state.booking.customerName;
                  works = state.booking.worksNameList;
                  bookingPrice = state.booking.bookingPrice;
                  collectedOnDate = state.booking.collectedOnDate;
                });
              }
            }),
          ],
          child: Container(

Это ListView элемент onTap:

onTap: () {
  // sending push here does work...
  //BlocProvider.of<PushNotificationBloc>(
  //context).add(
  //BookingStartedPushNotification(
  //booking: bookings[index]));
  if (isSelected[index] == false) {
    //store booking in a variable for sending notifications
    selectedBooking = index;
    print(
      'selected booking is ${bookings[selectedBooking].toMap().toString()}');
    //load selected booking
    BlocProvider.of<BookingBloc>(context).add(
      LoadBookingDetails(
        DateTime.fromMillisecondsSinceEpoch(
          bookings[index].bookingStart),
      ),
    );
  } else {
    setState(() {
      //selectedBooking = null;
      print(
        'selected booking is ${bookings[selectedBooking].toMap().toString()}');
      bookingId = '';
      bookingDate = '';
      bookingStart = '';
      bookingEnd = '';
      customerName = '';
      works = '';
      bookingPrice = '';
      bookingState = '';
      collectedOnDate = '';
    });
  }
setState(() {
  //invert isSelected value
  isSelected[index] = !isSelected[index];
}

и это кнопка onPressed :

onPressed: () {
  print("Started button is been clicked");
  //cache.play(
  //'tableViewClose.mp3');
  print(
    'selected booking is : ${bookings[selectedBooking].toMap().toString()}');
  try {
    BlocProvider.of<PushNotificationBloc>(
      context)
    .add(BookingStartedPushNotification(
      booking:
      bookings[selectedBooking]));
  } catch (e) {
    print('Error is : $e');
  }

  BlocProvider.of<BookingBloc>(context).add(
    UpdateBookingState(
    user: widget.user,
    cityDb: widget.cityDb,
    regionDb: widget.regionDb,
    booking:
    bookings[selectedBooking],
    state: 'Started'));
}

1 Ответ

1 голос
/ 16 июня 2020

В вашем контексте в Buttons onPressed, вероятно, нет доступных PushNotificationBlo c или BookingBlo c. Ваше дерево виджетов находится внутри одного большого метода сборки и никогда не прерывается сборщиком. Таким образом, контекст, используемый в методе onPressed, - это контекст, переданный через Widget build(BuildContext context) вверху, который не имеет MultiBlocProvider в качестве предка.

Посмотрите на BlocProvider.of () не может найти Blo c здесь: https://bloclibrary.dev/# / faqs

Либо вставьте Builder где-нибудь в дереве виджетов, либо еще лучше разделите вашу функцию сборки на несколько виджетов. Это также упростит чтение вашего кода.

...