It seems as if flutter StreamBuilder omits data if more than one data event occurs before the builder method gets executed.
I tried the following code which I expected to show "1;2;3;4;5;6;" etc. after pressing the button 3 times. (Shouldn't the builder method be called once for each ctrl.add() call?)
However, only every second ctrl.add() call reaches the builder method resulting in the output "2;4;6;".
Do I misunderstand the StreamBuilder behaviour? Or how can I fix the code so that multiple data can be sent "simultaneously"?
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
String _text = "";
StreamController<int> ctrl = StreamController<int>();
void _incrementCounter() {
_counter++;
ctrl.add(_counter);
_counter++;
ctrl.add(_counter);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: ctrl.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
_text += "${snapshot.data};";
}
return Text(_text);
},
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: const Icon(Icons.add),
),
);
}
}
OK, I found the answer in the flutter github issues pointing to the StreamBuilder documentation:
The builder is called at the discretion of the Flutter pipeline, and will thus receive a timing-dependent sub-sequence of the snapshots that represent the interaction with the stream.
So StreamBuilder just cannot be used if it is necessary to catch all data. :(
I got rid of StreamBuilder now and use a ChangeNotifier instead.