Search code examples
flutterdartblocflutter-bloc

Flutter Bloc Provider Error: Cannot Find The Correct Provider


I am attempting to make an app and I wanted to use a Bloc provider to store a user's data when they create their account. I have the Firebase collection created with the fields already defined; however, when I attempt to run it in Flutter, I get a huge error. It essentially says that it cannot find the correct provider form my bloc. I'm not sure how to fix this error, so I would really appreciate some guidance :). I have attached a screenshot of the emulator screen with the error and possible reasons for the error, as well as my code:

image

Onboarding bloc code:

part 'onboarding_event.dart';
part 'onboarding_state.dart';

class OnboardingBloc extends Bloc<OnboardingEvent, OnboardingState> {
  final DatabaseRepository _databaseRepository;
  final StorageRepository _storageRepository;

  OnboardingBloc({
    required DatabaseRepository databaseRepository,
    required StorageRepository storageRepository,
  }) : 
  _databaseRepository = databaseRepository,
  _storageRepository = storageRepository,
  super(OnboardingLoading()) {
    on<StartOnboarding>(_onStartOnboarding);
    on<UpdateUser>(_onUpdateUser);
    on<UpdateUserImage>(_onUpdateUserImage);
  }

  Future<void> _onStartOnboarding(
    StartOnboarding event, 
    Emitter<OnboardingState> emit) 
    async {
      User user = User(
        id: '',
        name: '',
        birthdate: '',
        imageUrls: [],
        Goals: '',
        Interests: [],
        Focus: []);
        String documentId = await _databaseRepository.createUser(user);
        emit(OnboardingLoaded(user: user.copyWith(id: documentId)));
    }

  void _onUpdateUser(
    UpdateUser event, 
    Emitter<OnboardingState> emit) {
      if (state is OnboardingLoaded) {
        _databaseRepository.UpdateUser(event.user);
        emit(OnboardingLoaded(user: event.user));
      }
    }

  void _onUpdateUserImage(
    UpdateUserImage event, 
    Emitter<OnboardingState> emit) 
    async{
      if (state is OnboardingLoaded) {
        User user = (state as OnboardingLoaded).user;

        await _storageRepository.uploadImage(user, event.image);

        _databaseRepository.getUser(user.id!).listen((user) {
          add(UpdateUser(user: user));
        });
      }
    }
}

Account Onboarding Screen (where I mention the specific bloc):

class AccountOnboarding extends StatefulWidget {
  const AccountOnboarding({Key? key}) : super(key: key);
  static const String routeName = '/profile onboarding';

  static Route route() {
    return MaterialPageRoute(
      settings: const RouteSettings(name: routeName),
      builder: (context) => MultiBlocProvider(
        providers: [BlocProvider<OnboardingBloc>(
          create: (_) => OnboardingBloc(
            databaseRepository: DatabaseRepository(), 
            storageRepository: StorageRepository())
            ..add(StartOnboarding()),
        )], 
        child: const AccountOnboarding()));
  }

  @override
  State<AccountOnboarding> createState() => _AccountOnboardingState();
  
}

class _AccountOnboardingState extends State<AccountOnboarding> {

    static const List<Tab> tabs = <Tab>[
    Tab(text: 'Name'),
    Tab(text: 'Age and Profile'),
    Tab(text: 'Bio and Interests'),
    Tab(text: 'Selection')
  ];

  @override
  Widget build(BuildContext context) {

    return DefaultTabController(
      length: tabs.length,
       child: Builder(builder: (BuildContext context) {
        final TabController tabController = DefaultTabController.of(context)!;
        tabController.addListener(() {
          if (!tabController.indexIsChanging) {}
        });

    return BlocBuilder<OnboardingBloc, OnboardingState>(
      builder: (context, state) {
        if (state is OnboardingLoading) {
          return
          const Center(child: CircularProgressIndicator());
        }
        if (state is OnboardingLoaded) {
        return Scaffold(
          resizeToAvoidBottomInset: false,
          backgroundColor: const Color(0xff31708c),
          appBar: AppBar(
            automaticallyImplyLeading: false,
            backgroundColor: Colors.transparent,
            elevation: 0,
            title: Row(
              children: [
                Expanded(
                  child: Image.asset('assets/images/Logo_Strength.png',
                  height: 50),
                ),
                Expanded(
                  flex: 2,
                  child: RichText(
                              text: TextSpan(
                                style: GoogleFonts.montserrat(
                                  fontSize: 30),
                                  children: <TextSpan> [
                                    TextSpan(text: 'Stren', 
                                    style: GoogleFonts.montserrat(
                                      color: Colors.white, 
                                      fontWeight: FontWeight.bold, 
                                      letterSpacing: 1,
                                      shadows: [
                                        Shadow(
                                          color: Colors.black.withOpacity(0.7),
                                          offset: const Offset(1.5, 0.0))
                                      ])),
                
                                    TextSpan(text: ';', 
                                    style: GoogleFonts.montserrat(
                                      color: const Color(0xffef6a7a), fontWeight: FontWeight.bold, 
                                      letterSpacing: 1,
                                      shadows: [
                                        Shadow(
                                          color: Colors.black.withOpacity(0.7),
                                          offset: const Offset(1.5, 0.0))
                                      ])),
                
                                    TextSpan(text: 'th', 
                                    style: GoogleFonts.montserrat(
                                      color: Colors.white, 
                                      fontWeight: FontWeight.bold, 
                                      letterSpacing: 1,
                                      shadows: [
                                        Shadow(
                                          color: Colors.black.withOpacity(0.7),
                                          offset: const Offset(1.5, 0.0))
                                      ]))
                          ],
                        ),
                      ),
                ),
              ],
            )
        ),
        body: TabBarView(
          // physics: const NeverScrollableScrollPhysics(),
          children: [
            NamePage(tabController: tabController,),
            ageAndPicture(tabController: tabController,),
            bioAndInterests(tabController: tabController,),
            SelectionPage(tabController: tabController,)
          ],
        ),
        );
      }
      else {return
        const Text('Something went wrong.');
      }
      }
    );
    
  }));
}}

Main dart:

int? isViewed;
Future <void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  await FirebaseAppCheck.instance.activate();
  
  final prefs = await SharedPreferences.getInstance();
  final showLogin = prefs.getBool('showLogin') ?? false;
  Paint.enableDithering = true;
  
// This is for our onboarding screen
isViewed = prefs.getInt('onboard');

  runApp(MyApp(showLogin: showLogin));
}

class MyApp extends StatelessWidget {
  final bool showLogin;
  
  const MyApp({Key? key,
  required this.showLogin}) : super(key: key);


  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Strength',
      debugShowCheckedModeBanner: false,
      
      home: AccountOnboarding() // FINAL SCREEN IS SPLASH SCREEN
    );
  }
}


Solution

  • Try to add provider on main.dart. It can be on Material home:

     @override
      Widget build(BuildContext context) {
        return MultiBlocProvider(
          providers: [
            BlocProvider(
              create: (context) => OnboardingBloc ()
                ),
            ),
          ],
          child: const AccountOnboarding(), 
        );
      }
    
    
    class MyApp extends StatelessWidget {
      final bool showLogin;
    
      const MyApp({Key? key, required this.showLogin}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Strength',
          debugShowCheckedModeBanner: false,
          home: MultiBlocProvider(
            child: AccountOnboarding(),
            providers: [
              BlocProvider(
                create: (context) => OnboardingBloc(),
              )
            ],
          ),
        );
      }
    }
    
    

    More about flutter bloc