Triggering initial event in BLoC Triggering initial event in BLoC dart dart

Triggering initial event in BLoC


Your discomfort really has reason - no event should be fired from build() method (build() could be fired as many times as Flutter framework needs)

Our case is to fire initial event on Bloc creation

Possibilities overview

  1. case with inserting Bloc with BlocProvider - this is preferred way

create: callback is fired only once when BlocProvider is mounted & BlocProvider would close() bloc when BlocProvider is unmounted

    class ExampleScreenState extends StatelessWidget {          @override      Widget build(BuildContext context) {        return Scaffold(          body: BlocProvider(            create: (context) => ExampleBloc()..add(Fetch()), // <-- first event,             child: BlocBuilder<ExampleBloc, ExampleState>(              builder: (BuildContext context, state) {                ...              },            ),          ),        );      }    }
  1. case when you create Bloc in State of Statefull widget
class _ExampleScreenStateState extends State<ExampleScreenState> {  ExampleBloc _exampleBloc;  @override  void initState() {    super.initState();    _exampleBloc = ExampleBloc();    _exampleBloc.add(Fetch());    // or use cascade notation    // _exampleBloc = ExampleBloc()..add(Fetch());  }  @override  void dispose() {    super.dispose();    _exampleBloc.close(); // do not forget to close, prefer use BlocProvider - it would handle it for you  }  @override  Widget build(BuildContext context) {    return Scaffold(      body: BlocBuilder<ExampleBloc, ExampleState>(        bloc: _exampleBloc,        builder: (BuildContext context, state) {         ...        },      ),    );  }}
  1. add first event on Bloc instance creation - this way has drawbacks when testing because first event is implicit
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {  ...  ExampleBloc() {    add(Fetch());  }}// insert it to widget tree with BlocProvider or create in StateBlocProvider( create: (_) => ExampleBloc(), ...// or in Stateclass _ExampleScreenStateState extends State<ExampleScreenState> {  final _exampleBloc = ExampleBloc(); ...

PS feel free to reach me in comments


Sergey Salnikov has a great answer. I think I can add another suggestion however.

In my main.dart file I am using a MultiBlocProvider to create all my blocs for use further down the tree. Like so

Widget build(BuildContext context) {    return MultiBlocProvider(      providers: <BlocProvider<dynamic>>[        BlocProvider<OneBloc>(create: (_) => OneBloc()),        BlocProvider<TwoBloc>(create: (_) => TwoBloc()),      ],      child: MaterialApp( // Rest of your app )

Then when I need to call an event when I load a page, in this case I wanted to fetch some data depending on a list tile selected, and I needed more options than FutureBuilder can provide me, I simple used initState(); and called the bloc provider and added an event.

class _ExampleScreenState extends State<ExampleScreen> {      @override  void initState() {    super.initState();    BlocProvider.of<OneBloc>(context)        .add(FetchData);  }

It works because the bloc has already been provided from the root widget.