title: How to call dispose when using BLoC pattern and StatelessWidget
body: <p>I am trying to understand BLoC pattern but I cannot figure out where or when to call dispose() in my example.</p>
  
  <p>I am trying to understand various state management techniques in Flutter.</p>
  
  <p>I came up with an example I managed to build with the use of StatefulWidget, scoped_model and streams.</p>
  
  <p>I believe I finally figured out how to make my example work with the use of "BloC" pattern but I have a problem with calling the dispose() method as I use the StatelessWidgets only.</p>
  
  <p>I tried converting PageOne and PageTwo to StatefulWidget and calling dispose() but ended up with closing the streams prematurely when moving between pages.</p>
  
  <p>Is it possible I should not worry at all about closing the streams manually in my example?</p>
  
  <pre><code>import 'package:flutter/material.dart';
  import 'dart:async';
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return StreamBuilder&lt;ThemeData&gt;(
        initialData: bloc.themeProvider.getThemeData,
        stream: bloc.streamThemeDataValue,
        builder: (BuildContext context, AsyncSnapshot&lt;ThemeData&gt; snapshot) {
          return MaterialApp(
            title: 'bloc pattern example',
            theme: snapshot.data,
            home: BlocPatternPageOne(),
          );
        },
      );
    }
  }
  
  // -- page_one.dart
  
  class BlocPatternPageOne extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('(block pattern) page one'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: &lt;Widget&gt;[
              buildRaisedButton(context),
              buildSwitchStreamBuilder(),
            ],
          ),
        ),
      );
    }
  
    StreamBuilder&lt;bool&gt; buildSwitchStreamBuilder() {
      return StreamBuilder&lt;bool&gt;(
              initialData: bloc.switchProvider.getSwitchValue,
              stream: bloc.streamSwitchValue,
              builder: (BuildContext context, AsyncSnapshot&lt;bool&gt; snapshot) {
                return Switch(
                  value: snapshot.data,
                  onChanged: (value) {
                    bloc.sinkSwitchValue(value);
                  },
                );
              },
            );
    }
  
    Widget buildRaisedButton(BuildContext context) {
      return RaisedButton(
              child: Text('go to page two'),
              onPressed: () {
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (BuildContext context) {
                      return BlocPatternPageTwo();
                    },
                  ),
                );
              },
            );
    }
  }
  
  // -- page_two.dart
  
  class BlocPatternPageTwo extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('(bloc pattern) page two'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: &lt;Widget&gt;[
              buildRaisedButton(context),
              buildSwitchStreamBuilder(),
            ],
          ),
        ),
      );
    }
  
    StreamBuilder&lt;bool&gt; buildSwitchStreamBuilder() {
      return StreamBuilder&lt;bool&gt;(
              initialData: bloc.switchProvider.getSwitchValue,
              stream: bloc.streamSwitchValue,
              builder: (BuildContext context, AsyncSnapshot&lt;bool&gt; snapshot) {
                return Switch(
                  value: snapshot.data,
                  onChanged: (value) {
                    bloc.sinkSwitchValue(value);
                  },
                );
              },
            );
    }
  
    Widget buildRaisedButton(BuildContext context) {
      return RaisedButton(
              child: Text('go back to page one'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            );
    }
  }
  
  // -- bloc.dart
  
  class SwitchProvider {
    bool _switchValue = false;
  
    bool get getSwitchValue =&gt; _switchValue;
  
    void updateSwitchValue(bool value) {
      _switchValue = value;
    }
  }
  
  class ThemeProvider {
    ThemeData _themeData = ThemeData.light();
  
    ThemeData get getThemeData =&gt; _themeData;
  
    void updateThemeData(bool value) {
      if (value) {
        _themeData = ThemeData.dark();
      } else {
        _themeData = ThemeData.light();
      }
    }
  }
  
  class Bloc {
    final StreamController&lt;bool&gt; switchStreamController =
        StreamController.broadcast();
    final SwitchProvider switchProvider = SwitchProvider();
  
    final StreamController&lt;ThemeData&gt; themeDataStreamController =
        StreamController();
    final ThemeProvider themeProvider = ThemeProvider();
  
    Stream get streamSwitchValue =&gt; switchStreamController.stream;
    Stream get streamThemeDataValue =&gt; themeDataStreamController.stream;
  
    void sinkSwitchValue(bool value) {
      switchProvider.updateSwitchValue(value);
      themeProvider.updateThemeData(value);
      switchStreamController.sink.add(switchProvider.getSwitchValue);
      themeDataStreamController.sink.add(themeProvider.getThemeData);
    }
  
    void dispose() {
      switchStreamController.close();
      themeDataStreamController.close();
    }
  }
  
  final bloc = Bloc();
  </code></pre>
  
  <p>At the moment everything works, however, I wonder if I should worry about closing the streams manually or let Flutter handle it automatically.</p>
  
  <p>If I should close them manually, when would you call dispose() in my example?</p>