0

I am trying to dispose rxsubject on the bloc. But when I call the dispose method on UI part, it throws error saying :

Bad state: Cannot add new events after calling close

Here's my bloc.

class EventBloc {
  final EventRepository _repository = EventRepository();
  final BehaviorSubject<EventResponse> _subject =
      BehaviorSubject<EventResponse>();
  getEvents() async {
    EventResponse response = await _repository.getEvents();
    _subject.sink.add(response);
  }

  dispose() {
    _subject?.close();
  }

  BehaviorSubject<EventResponse> get subject => _subject;
}

final eventBloc = EventBloc();

dispose method in UI:

void dispose() {
    super.dispose();
    eventBloc.dispose();
  }

When I am not calling dispose method on the UI, it works. Should I not call dispose method at all? If not, how should I dispose it?

Solution

moving final eventBloc=EventBloc(); from bloc and initializing bloc in UI.

Previously, without closing the subject, my UI would retain the data and when I navigated to the events page, the data would already be displayed there until api call succeed and when it did, it would simply rebuild listview with new data. But now, every time I navigate to the events page, all the progress is lost. Streambuilder starts from the very beginning of api call and until snapshot, it shows progress indicator and then data. It is like using PublishSubject.

Also, I heard an argument about not having to dispose stream when bloc is initialized within the bloc since the widget doesn't create the subject. How much is that true? Doesn't that lead to memory leaks?

Zero Live
  • 1,653
  • 5
  • 22
  • 44

1 Answers1

1

To prevent your data from getting lost, you can make use of provider. You'll need to create your bloc a level higher than the widget that uses it, ideally at the top level of the app. Like this:

  runApp(
    Provider<EventBloc>(
      create: (_) => EventBloc(),
      dispose: (context, value) => value.dispose(),
      child: MyApp(),
    ),
  );

Then your widget can access it when it needs it. Like:

  @override
  build(context) {
    final EventBloc eventBloc = Provider.of<EventBloc>(context);

    //Rest of your code
  }
Victor Eronmosele
  • 7,040
  • 2
  • 10
  • 33