flutter: Unhandled Exception: Bad state: Cannot add new events after calling close

后端 未结 6 857
清酒与你
清酒与你 2021-01-01 12:01

I am trying to use the bloc pattern to manage data from an API and show them in my widget. I am able to fetch data from API and process it and show it, but I am using a bott

相关标签:
6条回答
  • 2021-01-01 12:41

    @cwhisperer is absolutely right. Initialize and dispose your block inside widget just like bellow.

    final ServiceBloc serviceBloc = new ServiceBloc();
    
      @override
      void initState() {
        serviceBloc.getAllServices();
        super.initState();
      }
    
      @override
      void dispose() {
        serviceBloc.dispose();
        super.dispose();
      }
    

    and delete ServiceBloc serviceBloc = new ServiceBloc(); from your class ServiceBloc

    0 讨论(0)
  • 2021-01-01 12:43

    besides the provided solution I think you should also drain the stream allServices used in your ServiceBloc with:

    @override
    void dispose() {
          ...
          allServices?.drain(); 
    }
    
    0 讨论(0)
  • 2021-01-01 12:47
    ServiceBloc serviceBloc = new ServiceBloc();
    

    // remove this code // don't init class in the same page that will cause of bad state.

    0 讨论(0)
  • 2021-01-01 12:51

    I run into same error and noticed that if you check isClosed, the screen is not updated. In your code you have to remove the last line from Bloc file:

    ServiceBloc serviceBloc = new ServiceBloc();
    

    and put this line in CategoryPage just before the initState(). This way your widget is creating and disposing the bloc. Before, the widget only disposes the bloc but it is never re-created when the widget is re-created.

    0 讨论(0)
  • 2021-01-01 12:53

    If the error is actually caused by the code you posted, I'd just add a check to ensure no new events are added after dispose() was called.

    class ServiceBloc extends MainBloc {
      final _repo = new Repo();
      final PublishSubject<ServiceModel> _serviceController =
          new PublishSubject<ServiceModel>();
      Observable<ServiceModel> get allServices => _serviceController.stream;
      getAllServices() async {
        // do nothing if already disposed
        if(_isDisposed) {
          return;
        }
        appIsLoading();
        ServiceModel movieItem = await _repo.getAllServices();
        _serviceController.sink.add(movieItem);
        appIsNotLoading();
      }
    
      bool _isDisposed = false;
      void dispose() {
        _serviceController.close();
        _isDisposed = true;
      }
    }
    
    ServiceBloc serviceBloc = new ServiceBloc();
    
    0 讨论(0)
  • 2021-01-01 12:58

    Use StreamController.isClosed to check if the controller is closed or not, if not closed add data to it.

    if (!_controller.isClosed) 
      _controller.sink.add(...); // safe to add data as _controller isn't closed yet
    

    From Docs:

    Whether the stream controller is closed for adding more events.

    The controller becomes closed by calling the close method. New events cannot be added, by calling add or addError, to a closed controller.

    If the controller is closed, the "done" event might not have been delivered yet, but it has been scheduled, and it is too late to add more events.

    0 讨论(0)
提交回复
热议问题