// assume we have the following stream
Stream<int> numbersStream() async* {
var i = 0;
yield i;
for (i; i < 100; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
// and the following state
class _MyNumberStreamState extends State<MyNumberStream> {
// Assign the stream to an object.
final stream = numbersStream();
@override
Widget build(BuildContext context) {
return Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: StreamBuilder<int>(
initialData: 0,
key: const ValueKey('myStream'),
// If we pass `numbersStream()` directly to `StreamBuilder(stream: numbersStream())`,
// then on every build call (e.g. setState or when a parent rebuilds), a new subscription
// is created. The reason is simply that `numbersStream()` is returning a different object
// on each call. After each build, StreamBuilder compares the old stream vs the new stream,
// and if they're different, it'll create a new subscription, otherwise it keeps the old one.
// So if `numbersStream()` returns the same object, then assigning directly won't be an issue.
stream: stream, // numbersStream()
builder: (context, snapshot) {
return Text(snapshot.data.toString());
},
),
),
TextButton(
child: const Text('Set State'),
// click the button to observe the behavior in both cases
onPressed: () => setState(() {}),
),
],
);
}
}