Home > Software design >  Flutter: Context in FloatingActionButton cannot find the provider of <Bloc>
Flutter: Context in FloatingActionButton cannot find the provider of <Bloc>

Time:12-30

It's my first time using the BLoC pattern in Flutter. I have ran into a problem with providers and context. Here is my main.dart file.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:my_rescue/modules/screens/homepage/bloc/homepage_bloc.dart';
import 'package:my_rescue/widgets/drawer.dart';
import 'package:my_rescue/widgets/text_button.dart';
import 'package:my_rescue/widgets/weather_forecast.dart';
import 'package:my_rescue/widgets/app_bar.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(create: (BuildContext context) => HomepageBloc()..add(LoadHomepage())),
      ],
      child: Scaffold(
        appBar: const UpperNavBar().build(context),
        endDrawer: const CustomDrawer(),
        body: Center(
          child: BlocBuilder<HomepageBloc, HomepageState>(
            builder: (context, state) {
              if (state is HomepageInitial) {
                return CircularProgressIndicator(
                    color: Theme.of(context).colorScheme.primary);
              }
              if (state is HomepageNoEmergency) {
                return Column(
                  children: <Widget>[
                    const WeatherForecast(),
                    CustomTextButton(
                      height: 70,
                      text: "Safe Places",
                      icon: Icon(
                        Icons.map_outlined,
                        color: Theme.of(context).colorScheme.secondary,
                      ),
                      textStyle: Theme.of(context).textTheme.titleLarge,
                    )
                  ],
                );
              }
              if (state is HomepageEmergency) {
                return Column(
                  children: <Widget>[
                    const WeatherForecast(),
                    CustomTextButton(
                      height: 70,
                      text: "Safe Places",
                      icon: Icon(
                        Icons.map_outlined,
                        color: Theme.of(context).colorScheme.secondary,
                      ),
                      textStyle: Theme.of(context).textTheme.titleLarge,
                    ),
                    CustomTextButton(
                        height: 100,
                        text: "HELP!",
                        textStyle: Theme.of(context).textTheme.titleLarge)
                  ],
                );
              } else {
                return const Center(
                  child: Text("Something went wrong"),
                );
              }
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            context.read<HomepageBloc>().add(EmergencyHappened());
          },
        ),
      ),
    );
  }
}

The floatingActionButton is just to test whether are the events and states running well. However, when I press the button on my Android emulator, it tells me

Could not find the correct Provider above this HomePage Widget

After doing some research, I found that MultiBlocProvider should be able to provide the context for the rest of the widget tree. In my case, this includes the FloatingActionButton. However, it doesn't seem to be passing the context.

Any help is appreciated! Thanks a lot in advance!

I've also tried using BlocProvider and BlocProvider.of<HomepageBloc>(context).add(EmergencyHappened()). But that also tells me that HomepageBloc cannot be found. I'm expecting that the button works fine, and it is able to change the state to show the "HELP" button in my applicaiton. I also understand some questions on the internet involves Navigator pushing and popping pages, however mine is just within the same page. Nothing extra.

CodePudding user response:

The issue is that the context you're trying to get the bloc with is the build() so it searches in the external tree of it, but your bloc is internal, so you need a new context that can get it.

wrap your FloatingActionButton with a Builder like this:

floatingActionButton: Builder(
  builder: (context) {
    return FloatingActionButton(
          onPressed: () {
            context.read<HomepageBloc>().add(EmergencyHappened());
          },
        );
    }
  ),

this will make the lookup starts from the Builder's context.

  • Related