skip to Main Content

I’m encountering the following error in my Flutter application:
Error: Could not find the correct Provider<SettingsBloc> above this BlocListener<SettingsBloc, SettingsState> Widget.

I’m using the GetIt and Injectable packages for dependency injection. Below are the relevant parts of my code:

settings_bloc.dart

@lazySingleton
class SettingsBloc extends HydratedBloc<SettingsEvent, SettingsState> { 
  // Bloc implementation
}

settings_page.dart

class SettingsPage extends StatelessWidget {
  const SettingsPage({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocListener<SettingsBloc, SettingsState>(
      listenWhen: (previous, current) => previous.locale != current.locale,
      listener: (context, state) => context.setLocale(state.locale),
      child: BlocBuilder<SettingsBloc, SettingsState>(
        builder: (context, state) {
          return Scaffold();
        },
      ),
    );
  }
}

app_router.dart

GoRoute(
  path: '/tools',
  pageBuilder: (context, state) => CustomTransitionPage(
    key: state.pageKey,
    child: ToolsPage(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) =>
        FadeThroughTransition(
      animation: animation,
      secondaryAnimation: secondaryAnimation,
      child: child,
    ),
  ),
  routes: [
    GoRoute(
      path: 'settings',
      pageBuilder: (context, state) => CustomTransitionPage(
        key: state.pageKey,
        child: BlocProvider.value(
          value: getIt<SettingsBloc>(),
          child: const SettingsPage(),
        ),
        transitionsBuilder: (context, primaryAnimation, secondaryAnimation, child) =>
            FadeThroughTransition(
          animation: primaryAnimation,
          secondaryAnimation: secondaryAnimation,
          child: child,
        ),
      ),
      routes: [
        GoRoute(
          path: 'theme_selection',
          pageBuilder: (context, state) => CustomTransitionPage(
            key: state.pageKey,
            child: const ThemeSelectionPage(),
            transitionsBuilder: (context, animation, secondaryAnimation, child) =>
                FadeThroughTransition(
              animation: animation,
              secondaryAnimation: secondaryAnimation,
              child: child,
            ),
          ),
        ),
      ],
    ),
  ],
),

injection.config.dart

extension GetItInjectableX on GetIt {
  GetIt init({
    String? environment,
    EnvironmentFilter? environmentFilter,
  }) {
    final gh = GetItHelper(
      this,
      environment,
      environmentFilter,
    );
    final injectableModule = _$InjectableModule();
    gh.factory<FirebaseAuth>(() => injectableModule.firebaseAuth);
    gh.factory<GoogleSignIn>(() => injectableModule.googleSignIn);
    gh.singleton<Logger>(() => injectableModule.logger);
    gh.singleton<NotificationService>(() => injectableModule.notificationService);
    gh.lazySingleton<SettingsBloc>(() => SettingsBloc());
    // Other dependencies...
    return this;
  }
}

class _$InjectableModule extends InjectableModule {}

Issue:

When navigating to the SettingsPage, I receive the error stating that the Provider<SettingsBloc> cannot be found above the BlocListener. I’ve ensured that SettingsBloc is registered as a lazySingleton in GetIt and provided it using BlocProvider.value in the router.

Question:

What could be causing the Provider<SettingsBloc> not to be found above the BlocListener, and how can I resolve this issue to ensure that SettingsBloc is properly provided to the SettingsPage?

I attempted to wrap the MaterialApp.router() with a MultiBlocProvider and include SettingsBloc as one of the providers. Here is the code snippet:

@override
Widget build(BuildContext context) {
  return MultiBlocProvider(
    providers: [
      BlocProvider(create: (_) => getIt<AuthBloc>()),
      BlocProvider(create: (_) => SettingsBloc()),
    ],
    child: MaterialApp.router(
      // ... other configurations
    ),
  );
}

2

Answers


  1. Anywhere you are using BlocListener or BlocBuilder or BlocConsumer, you can provide your bloc object like this (with GetIt):

              BlocListener(
                bloc: getIt<AuthBloc>(),
                listener: ...,
              ),
    
    Login or Signup to reply.
  2. @override
    Widget build(BuildContext context) {
      return MultiBlocProvider(
        providers: [
          BlocProvider(create: (_) => getIt<AuthBloc>()),
          BlocProvider(create: (_) => getIt<SettingsBloc>()), // <-- Change here
        ],
        child: MaterialApp.router(
          // ... other configurations
        ),
      );
    }
    

    As you have tagged your SettingsBloc as lazySingleton, I assume that you want to use it via service locator, not with direct creation

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search