1

I'm using the Provider package in Flutter to handle state in my app. I have a list in which I can load new items, so I need to be aware of its state (loaded or ready) to add loading progress indicators when needed.

The way I am doing this is having a service class (this class is at bottom) that handles a stream with the state of the list and the list itself; so, when a new state is listened from the state, the widget can ask the provider for the list of items with

Widget build(BuildContext context) {
var listProvider = Provider.of<ListProvider>(context);
return StreamBuilder(
      stream: listProvider.listState,
      initialData: ListState.ready,
      builder:...
      
      ... //next lines are placed inside the list builder (is a list of Text widgets)
        itemBuilder: (context, index) {
        return new Text(listProvider.list[index]);
        },

Inside the main class I am providing the service class to the widget three with in the next way

Provider(
  create: (_) => ListProductsProvider(),
  dispose: (_, prov) => prov.dispose(),
),

The problem is that the dispose callback is not being called, so the stream is never closed. This causes I can't access the screen that builds the list because it says:

Bad state: Stream has already been listened to.

list.provider.dart

class ListProvider {
  List<String> _items = [];
  ListState _state;

  final _listStateController = StreamController<ListState>();

  List<String> get list => _items;
  Stream<ListState> get listState => _listStateController.stream;

  void addItem(count) async {
    if (_state == ListState.loading) return; // this line prevent from loading more items when already loading
    _state = ListState.loading;
    _listStateController.add(_state);
    await Future.delayed(Duration(seconds: 2), () {});
    _state = ListState.ready;
    _listStateController.add(_state);
    _items.addAll(new List.generate(1, (_) => 'Inserted new item'));
  }

  void dispose() {
    _listStateController.close();
  }
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
DanielJaramillo
  • 181
  • 1
  • 4
  • 13

1 Answers1

0

There's nothing wrong with how you close the Stream from what I can see from the snippets that you've shared. The issue lies on that you're trying to listen to the Stream multiple times. Commonly, Streams can only be listened to once at a time. To avoid the error Stream has already been listened to., you can convert the Stream to a broadcast. Follow the answer posted on this question.

Omatt
  • 8,564
  • 2
  • 42
  • 144