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();
}
}