Flutter- Understanding the lifecycle of Provider, Bloc and when to dispose the stream

Ankur Prakash picture Ankur Prakash · Jan 19, 2019 · Viewed 8.5k times · Source

Need to understand when we should Bloc pattern and life cycle of Bloc (how to release objects holding memory)

I have a screen where I am fetching the data from the server and data will be used for a single screen only. I am using Bloc pattern to show the data.

When using the Bloc pattern, I have a screen where I am using StatelessWidget. I am trying to dispose of the stream on 'WillPopScope'. Once disposed of, the stream cannot be used anymore. Because visiting the same screen result in a crash as I have wrapped my MaterialApp with the Bloc.

  1. created a stream
    final _leaderBoardList = StreamController<List<dynamic>>.broadcast();
  1. disposing stream
    dispose() {
      print('_leaderBoardList disposed');
      _leaderBoardList.close();
    }
  1. wrapping Material App within the provider:
    LeaderBoardProvider(
        child: MaterialApp(
        title: 'Table View Fetch',
        theme: ThemeData(
          primarySwatch: Colors.teal,
        ),
        home: HomeScreen(),
      ),
      );
  1. Statelesswidget 'WillPopScope', I have commented dispose of code as currently bloc is created once as I understood:
  Widget build(BuildContext context) {

    print(' ListView fetch Build called');
    final bloc = LeaderBoardProvider.of(context);
    bloc.fetchLeaderBoards();
    return WillPopScope(
      onWillPop: () async {
        //bloc.dispose();
        return true;
      },
      child: bodyStack(context, bloc),
    );
  }

The first Question, Suppose I create a broadcast stream and remove dispose of code in 'WillPopScope', then everything works as expected but I think, this way, my Bloc hold a memory for app lifetime.

Second Question, How to handle such cases in which data is used within a screen. Is Bloc pattern recommended for this situation?

Answer

R&#233;mi Rousselet picture Rémi Rousselet · Jan 19, 2019

You should not dispose BLoC within WillPopScope.

It is the job of your "Provider" to handle the disposal of your BLoC: It should close streams when the provider widget is removed from the tree.

This is achieved by your Provider being a StatefulWidget (with an internal private InheritedWidget to expose the BLoC) and overriding dispose method.

See Flutter: How to correctly use an Inherited Widget? for an example (it's not related to BLoC and doesn't have a dispose, but the idea is similar).