Skip to content

Instantly share code, notes, and snippets.

@gppam
Created October 28, 2020 09:01
Show Gist options
  • Save gppam/6e091fe218610c674c45892946b027af to your computer and use it in GitHub Desktop.
Save gppam/6e091fe218610c674c45892946b027af to your computer and use it in GitHub Desktop.
[Flutter] my solution to get listen to an un-broadcasted, single stream again (because i don't want broadcasting?)

This solves my problem where I always get the error "Bad state: Stream has been listened to". I don't want to use broadcasting because I read that it accumulates instances and then it will affect performance and so... here's my solution. The point here is that when I listen to a single stream, it should close the listening by itself when I move to another page, just to prevent that error. I'm not a genius coder, but this is what I have come up with. If you're here because we have the same problem, then I hope this can help you.

  1. Declare your streams and your variables in your provider.
  class UserProvider with ChangeNotifier {
    StreamController<List<User>> myStream;
    List<User> _listData = []
  }
  1. Add a function that will fetch your stream, for example like this:
  Stream getAllDataStream() {
    myStream = StreamController<List<User>>();
    if (_listData.isNotEmpty) myStream.add(_listData);
    return myStream.stream;
  }
  1. In your stateful/stateless widget create the provider instance in initState() then start listening in the build, like this:
  UserProvider provider;
  Stream<dynamic> userStream;
  
  @override
  void initState() {
    super.initState();
    provider =
        Provider.of<UserProvider>(context, listen: false);
  }
  
  @override
  Widget build(BuildContext context) {
    userStream = provider.myStream == null
      ? provider.getAllDataStream()
      : provider.myStream.stream;
  }
  1. Add a close function in your provider, close your stream and set it to null in the whenComplete() function, as shown below:
  Future<void> closeStream() async {
    await myStream
        .close()
        .whenComplete(() => myStream = null);
  }
  1. Lastly call this closeStream() in the deactivate() method.
  @override
  void deactivate() async {
    await provider.closeStream();
    super.deactivate();
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment