felangel / bloc

A predictable state management library that helps implement the BLoC design pattern
https://bloclibrary.dev
MIT License
11.79k stars 3.39k forks source link

Question: bug or misuse? #4022

Closed warcayac closed 8 months ago

warcayac commented 10 months ago

My application using Cubits (with flutter_bloc v8.1.3) was working fine days ago, but when I started adding files (not modifying the existing ones) for my authentication module then the application started generating this error message:

Launching /.../my_tmdb_app/lib/main.dart on Pixel 3a in debug mode...
✓  Built build/app/outputs/flutter-apk/app-debug.apk.
Connecting to VM Service at ws://127.0.0.1:41071/c47qBNjr-Z8=/ws

════════ Exception caught by widgets library ═══════════════════════════════════
The following ProviderNotFoundException was thrown building GeneralBlocBuilder<PopularMoviesCubit>:
Error: Could not find the correct Provider<PopularMoviesCubit> above this BlocBuilder<PopularMoviesCubit, PageState<Object>> Widget

This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:

- You added a new provider in your `main.dart` and performed a hot-reload.
  To fix, perform a hot-restart.

- The provider you are trying to read is in a different route.

  Providers are "scoped". So if you insert of provider inside a route, then
  other routes will not be able to access that provider.

- You used a `BuildContext` that is an ancestor of the provider you are trying to read.

  Make sure that BlocBuilder<PopularMoviesCubit, PageState<Object>> is under your MultiProvider/Provider<PopularMoviesCubit>.
  This usually happens when you are creating a provider and trying to read it immediately.

  For example, instead of:

  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // Will throw a ProviderNotFoundError, because `context` is associated
      // to the widget that is the parent of `Provider<Example>`
      child: Text(context.watch<Example>().toString()),
    );
  }

  consider using `builder` like so:

  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // we use `builder` to obtain a new `BuildContext` that has access to the provider
      builder: (context, child) {
        // No longer throws
        return Text(context.watch<Example>().toString());
      }
    );
  }

If none of these solutions work, consider asking for help on StackOverflow:
https://stackoverflow.com/questions/tagged/flutter

The relevant error-causing widget was:
    PopularScreen PopularScreen:file:///.../my_tmdb_app/lib/config/routes/app_router.gr.dart:42:22

When the exception was thrown, this was the stack:
#0      Provider._inheritedElementOf (package:provider/src/provider.dart:343:7)
#1      Provider.of (package:provider/src/provider.dart:293:30)
#2      ReadContext.read (package:provider/src/provider.dart:649:21)
#3      _BlocBuilderBaseState.initState (package:flutter_bloc/src/bloc_builder.dart:130:36)
#4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:5602:55)
#5      ComponentElement.mount (package:flutter/src/widgets/framework.dart:5447:5)
...     Normal element mounting (10 frames)
#15     Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#16     MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#17     MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
...     Normal element mounting (120 frames)
#137    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#138    MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#139    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
...     Normal element mounting (135 frames)
#274    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#275    MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#276    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
...     Normal element mounting (50 frames)
#326    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#327    MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#328    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
...     Normal element mounting (362 frames)
#690    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#691    MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6871:36)
#692    MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6883:32)
...     Normal element mounting (77 frames)
#769    Element.inflateWidget (package:flutter/src/widgets/framework.dart:4326:16)
#770    Element.updateChild (package:flutter/src/widgets/framework.dart:3831:20)
#771    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#772    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#773    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#774    StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#775    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#776    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#777    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#778    ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#779    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#780    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#781    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#782    ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#783    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#784    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#785    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#786    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#787    StatefulElement.update (package:flutter/src/widgets/framework.dart:5657:5)
#788    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#789    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#790    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#791    StatelessElement.update (package:flutter/src/widgets/framework.dart:5547:5)
#792    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#793    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#794    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#795    ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#796    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#797    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#798    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#799    ProxyElement.update (package:flutter/src/widgets/framework.dart:5800:5)
#800    Element.updateChild (package:flutter/src/widgets/framework.dart:3815:15)
#801    ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5496:16)
#802    StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5634:11)
#803    Element.rebuild (package:flutter/src/widgets/framework.dart:5187:7)
#804    BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2895:19)
#805    WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:984:21)
#806    RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:457:5)
#807    SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1325:15)
#808    SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1255:9)
#809    SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:978:7)
#813    _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)
(elided 3 frames from class _Timer and dart:async-patch)
════════════════════════════════════════════════════════════════════════════════
Application finished.

Exited.

PopularMovies belongs to the General module very separate from the Authentication module, as I mentioned at the beginning I was adding files to the Authentication module without modifying anything from the General module, not even anything from the authentication module has been added to routes or as a provider, and the application started to show that error. I don't see the root cause. And it is not the first time that something similar has happened, in another application I had to start again because, as in this case, I could not determine where the error came from.

main.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart';

import 'config/exports.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  HydratedBloc.storage = await HydratedStorage.build(
    storageDirectory: kIsWeb ? HydratedStorage.webStorageDirectory : await getTemporaryDirectory()
  );

  await TMDB.init();
  runApp(const AppProviders(child: MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<BrightnessCubit, Brightness>(
      builder: (context, state) {
        return MaterialApp.router(
          title: 'My TMDB App',
          debugShowCheckedModeBanner: false,
          theme: AppTheme(brightness: state).getTheme,
          routerConfig: AppRouter().config(),
        );
      },
    );
  }
}

app_providers.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../../modules/general/3_presentation/1_state_managers/cubit/exports.dart';
import '../initializers/init_usecases.dart';
import '../theme/brightness_cubit.dart';

class AppProviders extends StatelessWidget {
  final Widget child;

  const AppProviders({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    final useCases = initGeneralUseCases();

    return MultiBlocProvider(
      providers: [
        BlocProvider(create: (_) => BrightnessCubit()),
        BlocProvider(create: (_) => PopularMoviesCubit(useCases)..call()),
        BlocProvider(create: (_) => SearchMoviesCubit(useCases)),
        BlocProvider(create: (_) => MovieDetailsCubit(useCases)),
      ], 
      child: child,
    );
  }
}

app_router.dart

import 'package:auto_route/auto_route.dart';

import 'app_router.gr.dart';

@AutoRouterConfig(replaceInRouteName: 'Screen,Route')
final class AppRouter extends $AppRouter {
  @override
  List<AutoRoute> get routes => [
    AutoRoute(
      page: DashboardRoute.page,
      initial: true,
      children: [
        AutoRoute(page: PopularRoute.page, initial: true),
        AutoRoute(page: SearchRoute.page),
        AutoRoute(page: ProfileRoute.page),
      ]
    ),
    AutoRoute(page: DetailsRoute.page),
  ];
}

app_router.gr.dart

// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// AutoRouterGenerator
// **************************************************************************

// ignore_for_file: type=lint
// coverage:ignore-file

// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'package:auto_route/auto_route.dart' as _i6;
import 'package:my_tmdb_app/app/screens/dashboard_screen.dart' as _i1;
import 'package:my_tmdb_app/modules/general/3_presentation/2_screens/details/details_screen.dart'
    as _i2;
import 'package:my_tmdb_app/modules/general/3_presentation/2_screens/popular/popular_screen.dart'
    as _i3;
import 'package:my_tmdb_app/modules/general/3_presentation/2_screens/profile/profile_screen.dart'
    as _i4;
import 'package:my_tmdb_app/modules/general/3_presentation/2_screens/search/search_screen.dart'
    as _i5;

abstract class $AppRouter extends _i6.RootStackRouter {
  $AppRouter({super.navigatorKey});

  @override
  final Map<String, _i6.PageFactory> pagesMap = {
    DashboardRoute.name: (routeData) {
      return _i6.AutoRoutePage<dynamic>(
        routeData: routeData,
        child: const _i1.DashboardScreen(),
      );
    },
    DetailsRoute.name: (routeData) {
      return _i6.AutoRoutePage<dynamic>(
        routeData: routeData,
        child: const _i2.DetailsScreen(),
      );
    },
    PopularRoute.name: (routeData) {
      return _i6.AutoRoutePage<dynamic>(
        routeData: routeData,
        child: const _i3.PopularScreen(),
      );
    },
    ProfileRoute.name: (routeData) {
      return _i6.AutoRoutePage<dynamic>(
        routeData: routeData,
        child: const _i4.ProfileScreen(),
      );
    },
    SearchRoute.name: (routeData) {
      return _i6.AutoRoutePage<dynamic>(
        routeData: routeData,
        child: const _i5.SearchScreen(),
      );
    },
  };
}

/// generated route for
/// [_i1.DashboardScreen]
class DashboardRoute extends _i6.PageRouteInfo<void> {
  const DashboardRoute({List<_i6.PageRouteInfo>? children})
      : super(
          DashboardRoute.name,
          initialChildren: children,
        );

  static const String name = 'DashboardRoute';

  static const _i6.PageInfo<void> page = _i6.PageInfo<void>(name);
}

/// generated route for
/// [_i2.DetailsScreen]
class DetailsRoute extends _i6.PageRouteInfo<void> {
  const DetailsRoute({List<_i6.PageRouteInfo>? children})
      : super(
          DetailsRoute.name,
          initialChildren: children,
        );

  static const String name = 'DetailsRoute';

  static const _i6.PageInfo<void> page = _i6.PageInfo<void>(name);
}

/// generated route for
/// [_i3.PopularScreen]
class PopularRoute extends _i6.PageRouteInfo<void> {
  const PopularRoute({List<_i6.PageRouteInfo>? children})
      : super(
          PopularRoute.name,
          initialChildren: children,
        );

  static const String name = 'PopularRoute';

  static const _i6.PageInfo<void> page = _i6.PageInfo<void>(name);
}

/// generated route for
/// [_i4.ProfileScreen]
class ProfileRoute extends _i6.PageRouteInfo<void> {
  const ProfileRoute({List<_i6.PageRouteInfo>? children})
      : super(
          ProfileRoute.name,
          initialChildren: children,
        );

  static const String name = 'ProfileRoute';

  static const _i6.PageInfo<void> page = _i6.PageInfo<void>(name);
}

/// generated route for
/// [_i5.SearchScreen]
class SearchRoute extends _i6.PageRouteInfo<void> {
  const SearchRoute({List<_i6.PageRouteInfo>? children})
      : super(
          SearchRoute.name,
          initialChildren: children,
        );

  static const String name = 'SearchRoute';

  static const _i6.PageInfo<void> page = _i6.PageInfo<void>(name);
}

Extra info:

Flutter 3.16.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision b0366e0a3f (5 days ago) • 2023-12-05 19:46:39 -0800
Engine • revision 54a7145303
Tools • Dart 3.2.3 • DevTools 2.28.4
adar2378 commented 9 months ago

You need to use

BlocProvider<BrightnessCubit> ...  // this Bloc type was missing
warcayac commented 9 months ago

@adar2378 where? be more specific please

adar2378 commented 9 months ago

With each BlocProvider you need to pass the Bloc type like BlocProvider

adar2378 commented 9 months ago

Please check your AppProviders widget

felangel commented 8 months ago

Closing for now since it appears there aren't any actionable next steps.