4

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?

creativecreatorormaybenot
  • 114,516
  • 58
  • 291
  • 402
Ankur Prakash
  • 1,417
  • 4
  • 18
  • 31

1 Answers1

3

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).

Rémi Rousselet
  • 256,336
  • 79
  • 519
  • 432
  • Understood, you are recommending this approach which you have answered here https://stackoverflow.com/a/51690319/2644723. – Ankur Prakash Jan 20 '19 at 02:44
  • 1
    Also in the same link, you have mentioned " InheritedWidget behaves the same way as other Widgets do. Their lifetime is really short: Usually not longer than one build call. If you want to store data for longer, InheritedWidget is not what you want. You'll need a State for that." Just to clarify, here you mean state using GlobalKey as key? – Ankur Prakash Jan 20 '19 at 06:27
  • No. Using an actual State subclass – Rémi Rousselet Jan 20 '19 at 06:35
  • `_ViewControllerState createState() => _ViewControllerState();` `}` `class _ViewControllerState extends State {` ` // the widget's persistent state goes here` ` @override` `Widget build(BuildContext context) {` `// return a widget based on the persistent state` ` }` `}` Do you mean this by State subclass? Can you please quote an example. – Ankur Prakash Jan 20 '19 at 12:44