Hoping someone(s) can help explain to me why this happens cause it's not making sense to me and has been annoyingly taken days to figure out what was causing this issue.
The basic situation is when I define the StreamController globally it works fine, but once I try to define it within function the StreamBuilder never gets notified of new data/messages:
class _MyHomePageState extends State<MyHomePage> {
static StreamController<bool?>? streamController = StreamController(); // Works
// static StreamController<bool?>? streamController; // Doesn't work
static void start() async {
// streamController = StreamController(); // Doesn't work
streamController!.sink.add(true);
}
@override
Widget build(BuildContext context) {
...
StreamBuilder<bool?>(
stream: streamController?.stream,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.active:
_counter++;
continue keepGoing;
keepGoing:
case ConnectionState.done:
case ConnectionState.waiting:
return Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
);
case ConnectionState.none:
return const CircularProgressIndicator();
return const Placeholder();
default:
return const Text("Unknown State of Stream.");
}
}),
FloatingActionButton(
onPressed: () => start(),
tooltip: 'Increment',
child: const Icon(Icons.play_arrow_outlined),
),
...
}
}
My current guess is that the reference to the StreamController in the StreamBuilder never gets the updated reference but I'm doubtful of that since I believe the Widget's state should get updated with the button press. Any other suggestions and explanations would be great.
Thanks in advance.
As you have already realised, the reference is not updated. A button press doesn't trigger a rebuild (that wouldn't make sense either, because the button can't know if you cause a state change). You assign streamController?.stream
to your StreamBuilder
, which only does a rebuild at the beginning before you assign a value to streamController. If you want the UI to update itself when your State
changes, you should use setState
:
setState(() => streamController = StreamController())
Is it intended that the streamController
is static and reassigned every time a button is pressed without being closed first? Even if you use setState
here, no value will reach the StreamBuilder
because you call streamController.add(true)
before the actual rebuild has been performed and the StreamBuilder has received the new stream reference.
Or are you just trying out streams?