Cancelling a StreamSubscription in flutter - flutter

I have the following stream subscription
Stream<Uint8List> stream = await USBSerialSingleton.instance.inputStream;
usbStream = stream.listen(onDataReceivedFromUSBSerial);
The inputStream is a broadcast stream exposed like this.
Future<Stream<Uint8List>> get inputStream async {
final UsbPort port = await this.port;
return port.inputStream.asBroadcastStream();
}
I would like to stop listening to the stream, so I am calling
usbStream.cancel();
But I keep receiving messages on my onDataReceivedFromUSBSerial method. I keep getting messages on the onDataReceivedFromUSBSerial even if I close the dialogue that all this is implemented on.
Question: How do I stop listening to my usbStream?

You have to await for the subscription cancelation so do:
await usbStream.cancel();

Related

Making parallel and concurrent SignalR requests in flutter using bloc

With latest flutter bloc version , the events are processed concurrently.
here's is the scenario.
How to make concurrent signal R requests and show the result of all the requests for each millisecond until certain condition.
Here's what I have done.
Able to do single signal R request and get the result with bloc.
Also able to do multiple Signal R request once the previous request has been done processing.
What I need
To make concurrent or parallel signal r request using bloc while already a signalR request is under processing.
The sample code of the bloc's event
on<eventName>(
(event, emit) async {
for (final element in event.files) {
await establishSignalRConnection(uploadChannelId, element.name);
final DocumentUpload uploadAttachment =
await _Repository.upload();
emit(uploadedState(
emittedStateProperty
));
}
},
);
Thanks in Advance.
You could do it like this:
on<eventName>(
(event, emit) async {
const results = await Future.wait(
event.files.map((element) {
await establishSignalRConnection(uploadChannelId, element.name);
return await _Repository.upload();
});
// results now is a list of DocumentUploads, after all of them finished in parallel
emit(uploadedState(emittedStateProperty));
}
);
Please note that opening that many connections and sending one file over each is probably slower than having a signalR endpoint that just accepts multiple files. So if you can change the backend, that might be the better way, performance wise.

Function returns before its finished

I'm trying to implement a socket connection between a python server and a flutter client,
everything works well, but when I want to get the response back the function returns null and then prints the response.
I'm receiving the response but after the function returns.
String rcev_response() {
String response = "";
socket.listen((event) {
response = utf8.decode(event);
print(response);
});
return response;
}
Any idea what's happening here and how can I fix it?
EDIT:
After a little bit of debugging, I found out that socket.listen() doesn't actually stop. so the function returns the value before its assigned
and I added a 1ms delay before the return and now it's working properly.
Timer(Duration(seconds: 1), onceAtTheEndOfTheBatch);
this is still not a solution. any help would be appreciated.
try to add async
Future<String> rcev_response() async {
String response = "";
await socket.listen((event) {
response = utf8.decode(event);
print(response);
});
return response;}
maybe this help you :)
The anonymous function that you are passing to listen is going to be called multiple times with chunks of the response. It's up to you to concatenate them. As you need a string you can use the stream join convenience function.
Future<String> rcev_response() async {
Socket s = await Socket.connect(ipAddr, port);
s.add(utf8.encode(request));
String result = await utf8.decoder.bind(s).join();
await s.close(); // probably need to close the socket
return result;
}
This assumes that the server will close the socket when it's finished sending.
A solution but still not optimal.
I found out that it works properly if I close the socket from the server side and re-initialize it every time I send a request from the client side.
For example - Server side process:
# accept connection
client_socket, client_address = self.server_socket.accept()
# receive the message
client_socket.recv()
# send response
client_socket.send()
# close socket
client_socket.close()
But I still want to keep the connection alive as a full duplex connection, if anyone can help.

listen to events on the client side only when a change has occurred Dart?

Is there some way to use a listener that listens for changes on the server and sends the changes to UI as soon as those changes happen? I'm using a websocket (singalr package to be exact) and I need to set up an event listener so that the client side captures all changes. I read that I need to use streams instead of futures and I can also subscribe to the event there, but is this suitable for the application to poll the server every time only when it actually changes, and not constantly? For example, I read that in a java script, you can use an event listener that independently "understand" that changes have occurred on the server side and pass them on to the frontend side (I am not a JS developer, but I have heard that JS has such functionality, so if there is something like this in Dart?). Right now I'm using the following code, but I'm not sure if it does exactly what I described
static Stream<String?> getData() =>
Stream.periodic(Duration(seconds: 1)).asyncMap((event) => fetchData());
static Future<String?> fetchData() async {
final hubConnection =
HubConnectionBuilder().withUrl('https://secure/secure').build();
await hubConnection.start();
String? values;
if (hubConnection.state == HubConnectionState.Connected) {
await hubConnection
.invoke('GetData')
.then((value) => values= value as String);
}
print('values');
hubConnection.onclose(({error}) {
throw Exception(error);
});
print(values);
return values;
}

Pattern for async request/response over TCP socket

I'm trying to implement a Dart client for the mpd protocol. mpd communicates over a TCP connection by exchanging text messages. A command is sent and terminated by \n. The server replies with one or multiple lines delimited by \n and ends a response with a OK or ACK message.
I'm struggling to implement a request / response approach due the async nature of Dart and the Socket class. I'm coming from Java & Go and the async approach is not natural to me.
This is how I want a caller to use the client:
MpdClient c = MpdClient('hostname', 6600);
await c.connect();
String response = await c.command('status');
print(response);
await c.close();
In the client, connecting is no issue:
Socket socket = await Socket.connect(hostname, port);
Then I'm not sure what to do with the socket and how to implement the Future<string> command(String cmd) function. I am able to listen() on the Socket and decode the response, but I don't see how I can tie that to a Future<string> returned by c.command(...).
I also tried to use the stream methods on Socket (which works well via .takeWhile() and .fold() to decode a response). Something like this:
Future<String> command(String cmd) {
String last = "";
return _stream
.map((event) => event.toList())
.transform(utf8.decoder)
.takeWhile((event) {
if (last.startsWith("OK") || last.startsWith("ACK")) {
return false;
} else {
last = event;
return true;
}
})
.fold("", (previous, element) => previous + element);
}
But the Socket stream can only be subscribed once, so this method cannot be called multiples times.
Is there a way to achieve what I want from the caller side with the Socket class? Or would I be better off using RawSocket and its read() method which offers a more low-level / controlled way to read the response?

Netty: when does writeAndFlush channel future listener callback get executed?

I am new to netty and trying to understand how the channel future for writeAndFlush works. Consider the following code running on a netty client:
final ChannelFuture writeFuture = abacaChannel.writeAndFlush("Test");
writeFuture.addListener(new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) throws Exception {
if (writeFuture.isSuccess()) {
LOGGER.debug("Write successful");
} else {
LOGGER.error("Error writing message to Abaca host");
}
}
});
When does this writeFuture operationComplete callback executed?
After netty hands over the data to the OS send buffers (or)
After the OS writes the data to the network socket. (or)
After this data is actually received by the server.
TIA
1. After netty hands over the data to the OS send buffers (or)
Listener will be notified after data is removed from ChannelOutboundBuffer (netty's send buffer)