Не удалось найти правильный Provider<TokenBloc> над этим виджетом приложения

Я использую BLoC. Как его правильно создать, что бы не возникало из-за отсутствия виджетов вниз по дереву виджетов. Теперь мне обычно нравится это:

    Widget build(BuildContext context) {
return MaterialApp(
    // debugShowCheckedModeBanner: false,
    theme: Styles.appTheme,

    home: BlocProvider<TokenBloc>(
      create: (context) => di.sl<TokenBloc>(),
      child: _childTokenBloc,
    ),
  );
}


   

 Widget get _childTokenBloc {
      return BlocBuilder<TokenBloc, TokenState>(builder: (context, state) {
        if (state is TokenInitialState) {
          context.read<TokenBloc>().add(TokenCheckEvent());
          return const LogoImage();
        }
        if (state is TokenCheckState) {
          return const LogoImage();
        }
    
        if (state is TokenOkState) {
          return MainPageWidget();
        }
    
        if (state is TokenNoAuthorizationState) {
          return const AuthorizationPageWidget();
        }
        return const LogoImage();
      }
      );
    }

В AuthorizationPageWidget я делаю:

Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const ConfirmAuthorizationPage()),
);

А из ConfirmAuthorizationPage пытаюсь обратиться к TokenBloc:

context.read<TokenBloc>().add(TokenAddEvent());

но получаю ошибку: Не удалось найти нужного провайдера над этим виджетом приложения.

Я думал, что TokenBloc будет найден в дереве виджетов, но не так ли? И как исправить эту проблему? Нужно использовать MultiBlocProvider в методе сборки виджета ConfirmAuthorizationPage? Он будет повторно инициализирован, а предыдущий использоваться не будет.


Обновление 1: Код AuthorizationPageWidget:

class AuthorizationPageWidget extends StatefulWidget {
  const AuthorizationPageWidget({Key? key}) : super(key: key);

  @override
  _AuthorizationPageWidgetState createState() =>
      _AuthorizationPageWidgetState();
}

class _AuthorizationPageWidgetState extends State<AuthorizationPageWidget> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocProvider<AuthorizationBloc>(
        create: (context) => sl<AuthorizationBloc>(),
        child: SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                _title,
                _description,
                Expanded(child: Align(alignment: FractionalOffset.bottomCenter, child: _bottomButton))
              ],
            ),
        ),
      ),
    );
  }


//......   

 
void pushConfirmPage(String number) {

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => ConfirmAuthorizationPage(number: number,)),
    );
  }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
19
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите предоставить свой блок во всех своих приложениях, вы должны написать его в своем MaterialApp вот так, а не в теле;

return 
    BlocProvider<TokenBloc>( // like this
       create: (context) => TokenBloc(),
       child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Flutter Demo',
          home: _TokenHome(),
       ),
    ),
);

class _TokenHome extends StatelessWidget { // use a class instead of function
  const _TokenHome({
    Key? key,
  }) : super(key: key);

@override
  Widget build(BuildContext context) {
    return BlocBuilder<TokenBloc, TokenState>(
      builder: (context, state) {
          if (state is TokenInitialState) {
            context.read<TokenBloc>().add(TokenCheckEvent());
            return const LogoImage();
          }
          if (state is TokenCheckState) {
            return const LogoImage();
          }
          if (state is TokenOkState) {
            return MainPageWidget();
          }
          if (state is TokenNoAuthorizationState) {
            return const AuthorizationPageWidget();
          }
          return Container(
            width: 50,
            height: 50,
            color: Colors.red,
          ); // use this if there is not a state
        }
    );
  }
}

Если по какой-то причине он больше ничего не показывает, то это потому, что некоторые из ваших классов, таких как AuthorizationPageWidget или LogoImage, неверны, проверьте это.

-------- РЕДАКТИРОВАТЬ

Использование БлокПровайдер на каждой странице может быть полезным, но имейте в виду, что, например, АвторизацияБлок будет работать только для своих дочерних элементов, если вы вызовете его на другой стороне экрана, он не будет работать, поэтому настоятельно рекомендуется использовать MultiBlocProvider в Материал Приложение. избежать проблем в будущем;

return MultiBlocProvider( // like this
  providers: [
    BlocProvider<TokenBloc>(
      create: (context) => TokenBloc(),
    ),
    BlocProvider<AuthorizationBloc>(
      create: (context) => AuthorizationBloc(),
    ),
  ],
  child: BlocBuilder<LanguageCubit, Locale?>(
    builder: (context, lang) {
      return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
      );
    },
  ),
);

Таким образом, все остальные БлокПровайдер, которые вы используете для их создания, удаления, они вам не нужны, теперь, если вы используете Блокбилдер, BlocListeners любого Блока, у вас не будет никаких неудобств.

Спасибо. Оно работает! Но по какой-то причине то, что я возвращаю в _childTokenBloc, не помещается на передний план. Я не вижу этого экрана, но по логам вижу, что он загрузился. Не подскажете, в чем может быть дело?

sergey_s 16.05.2022 12:27

Ммм, я редактирую это, проверьте!

Daniel Roldán 16.05.2022 13:04

Что с ними может быть не так? В AuthorizationPageWidget я использую новый блок - AuthorizationBloc.

sergey_s 16.05.2022 14:50

Все блоки, которые вы хотите использовать, должны быть в MaterialApp, с MultiBlocProvider, вы должны создать их там, вы это сделали?

Daniel Roldán 16.05.2022 14:52

Я добавил вопрос. Взгляни, пожалуйста. Разве MaterialApp не используется с основным блоком? его нужно дублировать на каждой странице? в MultiBlocProvider нужно подписаться на TokenBloc?

sergey_s 16.05.2022 15:06

Ок, редактирую, смотри

Daniel Roldán 16.05.2022 15:26

Другие вопросы по теме