How to call bloc event only once when the screen loads
Asked Answered
L

2

8

I'm using flutter_bloc library. My screen widget code looks looks this:

class RegisterScreen extends StatefulWidget {
  RegisterScreen();

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

class _RegisterScreenState extends State<RegisterScreen> {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<RegisterBloc>(
      create: (BuildContext context) {
        // RegisterBloc.get(context).add(RegisterGetCitiesEvent());<=== This gives me error `BlocProvider.of() called with a context that does not contain a Cubit of type RegisterBloc. \n No ancestor could be found starting from the context that was passed to BlocProvider.of<RegisterBloc>().`
        return RegisterBloc();
      },
      child: BlocConsumer<RegisterBloc, RegisterState>(
        listener: (BuildContext context, RegisterState state) {},
        builder: (BuildContext context, RegisterState state) {
          // RegisterBloc.get(context).add(RegisterGetCitiesEvent());<=== This line is executed infinite times
          return Scaffold(
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                RegisterBloc.get(context).add(RegisterGetCitiesEvent());
              },
              child: new Icon(Icons.refresh),
            ),
            body: Conteiner(
              child: Text(RegisterBloc.get(context).cities==null?'':RegisterBloc.get(context).cities,)
            ),
          );
        },
      ),
    );
  }
}

And the bloc file is like this:

class RegisterBloc extends Bloc<RegisterEvent, RegisterState> {
  static RegisterBloc get(BuildContext context) => BlocProvider.of(context);
  RegisterBloc() : super(RegisterInitial());

  String cities = '';

  @override
  Stream<RegisterState> mapEventToState(
    RegisterEvent event,
  ) async* {
    if (event is RegisterGetCitiesEvent) {
      yield* getCities();
    }
  }

  Stream<RegisterGetCitiesState> getCities() async* {
    yield await (CustomerServer.getCities()).then((res) {
      cities = res;
      return RegisterGetCitiesState();
    });
  }
}

In my code, I have to click on the FAB to call the RegisterGetCitiesEvent bloc event. How can I call that event immediately RegisterBloc.get(context).add(RegisterGetCitiesEvent()) without requiring the user to click on any button?

What I tried:

I tried to add that line in the BlocConsumer builder function, but the function executed infinite times.
I tried to add that line in the BlocProvider create function, but it gave me an error BlocProvider.of() called with a context that does not contain a Cubit of type RegisterBloc.

Where should I place this line RegisterBloc.get(context).add(RegisterGetCitiesEvent()) in order to call the RegisterGetCitiesEvent event automatically as soon as the screen shows(Without need to click on any button)?

Laterite answered 21/8, 2020 at 15:6 Comment(0)
T
7

I suggest you to read the BLoC documents completely. But here is a quick answer to this question: You should do that in BlocProvider's create function. Like this:

class RegisterScreen extends StatefulWidget {
  RegisterScreen();

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

class _RegisterScreenState extends State<RegisterScreen> {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<RegisterBloc>(
      create: (context) => RegisterBloc()..add(RegisterGetCitiesEvent())
    );
  }
}
Trivet answered 21/8, 2020 at 18:18 Comment(2)
Thanks @Trivet , in this above example, will the RegisterGetCitiesEvent() event gets triggered everytime this RegisterScreen is pushed to the nav stack?Baklava
Yes, it will get called @MikethetechyTrivet
D
0

You could get it by:

  1. set bloc provider out of that class
  2. create an initial state class for that bloc
  3. use it as default state in that bloc
  4. call that one function you want to call just once when bloc is on initial state

Example in DartPad: https://dartpad.dev/?id=79649d00b478758f07954deed2f82d32

Dorene answered 2/10, 2024 at 13:50 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.