Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call bloc event only once when the screen loads

Tags:

flutter

bloc

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)?

like image 667
Yazan W Yusuf Avatar asked Oct 27 '22 18:10

Yazan W Yusuf


1 Answers

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())
    );
  }
}
like image 80
Amir_P Avatar answered Nov 09 '22 10:11

Amir_P