Bloc: Bad state: Cannot add new events after calling close

Created on 15 Aug 2019  路  7Comments  路  Source: felangel/bloc

Describe the bug
Bad state: Cannot add new events after calling close

To Reproduce
Steps to reproduce the behavior:

  1. HomePage contains a list of items
  2. I pass the bloc to the list via the BlocProvider.builder
  3. Then I delete all lists (list.length = 0)
  4. Then, if I dispatch the event at the HomPage (click on the RaiseButton), it will report an error

Note: If I use BlocBuilder.value, the program works normally

class _HomePageState extends State<HomePage> {
  HomeBloc _bloc;
  List<Note> _listNote;

  @override
  void initState() {
    _bloc = HomeBloc(context: context);
    _bloc.dispatch(LoadNoteDataEvent());

    _listNote = List();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[100],
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              itemBuilder: (context, index) => BlocProvider(
                builder: (context) => _bloc,
                child: ItemWidget(),
              ),
              itemCount: _listNote.length,
            ),
          ),

          RaisedButton(
            child: Text('OK'),
            //The error was thrown when I pressed the button
            onPressed: () => _bloc.dispatch(HandleTapEvent()),
          )
        ],
      ),
    );
  }
}

question

Most helpful comment

This is expected behavior... BlocProvider manages the life cycle of the bloc and when it's disposed will also automatically dispose of the bloc. Which is why you are seeing the behavior you described. Using BlocProvider.value is the recommended way in this situation.

Check out the documentation here: https://felangel.github.io/bloc/#/flutterbloccoreconcepts?id=blocprovider

All 7 comments

This is expected behavior... BlocProvider manages the life cycle of the bloc and when it's disposed will also automatically dispose of the bloc. Which is why you are seeing the behavior you described. Using BlocProvider.value is the recommended way in this situation.

Check out the documentation here: https://felangel.github.io/bloc/#/flutterbloccoreconcepts?id=blocprovider

Hi @hahai96 馃憢
Thanks for opening an issue!

As @warriorCoder mentioned, when you use BlocProvider with a builder, then the BlocProvider will automatically dispose the bloc when BlocProvider is disposed. In addition, you should always create the bloc instance within the builder in order to avoid this type of issue.

If you really want to have the Bloc be created within this widget, then you have to use BlocProvider.value and manually dispose the bloc yourself. Alternatively, I'd suggest wrapping your HomePage in a BlocProvider like:

BlocProvider(
  builder: (context) => HomeBloc()..dispatch(LoadNoteDataEvent()),
  child: HomePage(),
)

Then everything should work as expected and you don't need to manually dispose and create the bloc within a StatefulWidget.

Some other things to consider are:

  • You should not be passing BuildContext to a bloc because you are coupling the bloc to Flutter and are making the business logic layer have a dependency on the presentation layer.
  • _listNote seems like it should be part of the bloc state instead of being separately maintained by the widget

Hope that helps! 馃憤

You should not be passing BuildContext to a bloc because you are coupling the bloc to Flutter and are making the business logic layer have a dependency on the presentation layer.

@felangel In case I need to use context, what should I do?

@hahai96 why do you need BuildContext within the bloc?

@felangel because I did not use respository, I will refactor my code.

BlocProvider(
  builder: (context) => HomeBloc()..dispatch(LoadNoteDataEvent()),
  child: HomePage(),
)

@felangel When will blocProvider dispose. For my original code, I think it was only dispose when the Homepage was dispose

@hahai96 it will dispose the bloc when the BlocProvider widget is disposed. In your original implementation, BlocProvider was being disposed before the HomePage was disposed and you were using dispatch outside of BlocProvider.

Was this page helpful?
0 / 5 - 0 ratings