Flutter : trigger a change of screen on a websocket message
You can use a stream for that. You can register the websocket response, and when it returns you can add it to the stream, and then on your screen you use a StreamBuilder to subscribe to the stream and navigate when needed. Something like this:
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
// Create a stream to receive the values
var webSocketStream = new BehaviorSubject<String>();
onMessageReceived(data) {
print("new message: " + data + " !");
data = jsonDecode(data);
data.forEach((key, value) {
switch (key) {
case "state":
// Write to the stream
webSocketStream.add(value);
break;
}
});
}
class CheckWebSocket extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<String>(
// Subscribe to the stream
stream: webSocketStream,
builder: (context, snapshot) {
// When the stream changes navigate
if (snapshot.hasData && snapshot.data == "start") {
Navigator.pushNamed(context, "/path");
} else {
return Container();
}
}),
);
}
}
I used rxdart for that, because it makes dealing with streams simpler. I also recommend that you extract the code that reads the websocket to a separate class, I put everything in one file just to make it simpler to understand.
Maël Gassmann
Updated on December 09, 2022Comments
-
Maël Gassmann over 1 year
I'm currently working on a flutter app with a websocket. I want to change the current screen with aNavigator.pushNamed(context, '/path')
in the method that is triggered by the websocket on a new message. The problem is that I don't have anycontext
in this method.So how to change the current screen from this method ?
I dont know if I'm thinking in the wrong way or if I just don't understand something.Here is the method that is triggered on a new websocket message, his class is not a widget. This object is contained in every screen I create but his variable
_parent
is always set to match the active screen.onMessageReceived(data) { print("new message: " + data + " !"); data = jsonDecode(data); data.forEach((key, value) { switch (key) { case "state": _parent.newState(value); break; } }); }
Here is the method of the widget:
newState(state){ if(state == "start"){ Navigator.pushNamed(, "/path"); } }
Thanks in advance
-
Mazin Ibrahim about 5 yearsis it necessary for you to navigate to other screen or you just want to show the data of the
websocket
? -
Maël Gassmann about 5 years@MazinIbrahim I really want to navigate to an another screen.
-
user3875913 almost 4 years@MaëlGassmann for this i think you need to call setState instead of new state to get the rerender
-
-
Maël Gassmann about 5 yearsThanks for your answer, When I implemented that in my app, I got an error because it couldn't finish to build before navigating : The following assertion was thrown building StreamBuilder<String>(dirty, state: I/flutter (32357): _StreamBuilderBaseState<String, AsyncSnapshot<String>>#489bf): I/flutter (32357): setState() or markNeedsBuild() called during build.
-
Ricardo Smania about 5 yearsI forgot to return an empty container if the snapshot has no data, please try again.
-
Maël Gassmann about 5 yearsStill, the same error is showing. Are you sure that you can navigate during build ?
-
Maël Gassmann about 5 yearsAnyway, I found a solution : If snapshot has no data I just show a different scaffold than if he has data. Thanks a lot.