StreamBuilder is not reading data from Stream as expected

Viewed 1015

I am trying to use a StreamBuilder to read some data from a Stream, but snapshot.data is only returning the last item from the Stream. In this case, I am only getting 'f'. I want to get 'a', 'b', 'c', 'd', 'e', 'f'. What am I doing wrong?

class ProgressWidget extends StatefulWidget {
  //ProgressWidget({this.stream}) : super();
  //final Stream<String> stream;

  @override
  _ProgressWidgetState createState() => _ProgressWidgetState();
}

class _ProgressWidgetState extends State<ProgressWidget> {
  int _progressCount = 0;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: Stream.fromIterable(['a', 'b', 'c', 'd', 'e', 'f']),  // test stream
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          _progressCount++;
          if (snapshot.hasData) {
            print(snapshot.data);
          }
          return snapshot.hasData
              ? new Text('Progress $_progressCount ' + snapshot.data)
              : new Text('Loading ... ');
        });
  }
}
2 Answers

Try this:

class _ProgressWidgetState extends State<ProgressWidget> {
  int _progressCount = 0;
  Stream<String> _stream;
  List<String> _source = ['a', 'b', 'c', 'd', 'e', 'f'];

  @override
  void initState() {
    super.initState();

    _stream = Stream.periodic(Duration(seconds: 1), (i) => _source[i]).take(_source.length);
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: _stream, // test stream
      builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
        _progressCount++;
        return snapshot.hasData ? new Text('Progress $_progressCount ' + snapshot.data) : new Text('Loading ... ');
      },
    );
  }
}

Create your stream like this:

Stream<String> listStream(Duration interval, List<String> list) async* {
      int i = 0;
      while (i<list.length) {
        await Future.delayed(interval);
        yield list[i];
        i++;
      }
    }

Final code:

class ProgressWidget extends StatefulWidget {
  //ProgressWidget({this.stream}) : super();
  //final Stream<String> stream;

  @override
  _ProgressWidgetState createState() => _ProgressWidgetState();
}

class _ProgressWidgetState extends State<ProgressWidget> {
  int _progressCount = 0;
  String str = '';
  @override
  void initState() {
    super.initState();
  }
Stream<String> listStream(Duration interval, List<String> list) async* {
  int i = 0;
  while (i<list.length) {
    await Future.delayed(interval);
    yield list[i];
    i++;
  }
}
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<String>(
        stream:listStream(Duration(milliseconds:300), ['a', 'b', 'c', 'd', 'e', 'f']),
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          _progressCount++;
          if (snapshot.hasData) {
            print(snapshot.data);
            str += snapshot.data;
          }
          return snapshot.hasData
              ? new Text('Progress $_progressCount ' + str)
              : new Text('Loading ... ');
        });
  }
}
Related