Reputation: 61
What are some ways to rebuild a class's widgets on value changes from a stream in a different class with no build context? Can't use setState from a different class unless I force it to update here using a timer, Provider needs context, ValueListenableBuilder didn't work. Do I need to add context to the class? That feels wrong though. I also could be using the above state management tools wrong, so if you think one of them can work, please point it out.
I have a version that functions using setState and periodic timers, but the accuracy of it is bad, so I need to have it update based on when the values from the stream change.
Code that outlines problem:
Here is a snippet of my singleton ble class that has a stream of data coming from a device.
Class outside of widget tree
Class BleInteractions {
static BleInteractions? _instance;
int? valueFromStream;
FlutterReactiveBle? ble;
static BleInteractions? get instance {
if (_instance == null) {
_instance = BleInteractions._internal();
}
return _instance;
}
BleInteractions._internal() {
ble = FlutterReactiveBle();
valueFromStream = null;
}
//stream function snippet
streamSubscription = ble?.subscribeToCharacteristic(characteristic).listen((data) async {
valueFromStream = data;
}
}
And here's a class that takes that value and needs to rebuild when the stream changes to a different value. There's a lot more happening in this class normally, but I've removed it all because even a basic example in an empty widget build would be useful to see.
Stateful widget class that needs to use values from above class
class ForceGraph extends StatefulWidget {
const ForceGraph({ Key? key}): super(key: key);
@override
State<ForceGraph> createState() => _ForceGraphState();
class _ForceGraphState extends State<ForceGraph> {
final bleInteractions = BleInteractions.instance;
@override
void initState() {
super.initState();
initPageAfterStream();
}
void initPageAfterStream() async {
streamStarted = activateStream();
}
Future<bool> activateStream() async {
//await stream function happens here
return Future.value(true);
}
@override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
future: streamStarted,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: Text('Please wait, page loading...'));
} else
return bleInteractions?.valueFromStream != null
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//normally have a graph that makes use of those values in here and in some other
functions, but even an updating text widget based on the new value from the stream
would be good.
Text(bleInteractions.valueFromStream)]
) : Container();
});
}
}
Upvotes: 0
Views: 407
Reputation: 8607
There are several ways to do it. I myself have used flutter_bloc
when dealing with streams from BLE devices. How it works:
Upvotes: 1