I'm new to dart and Flutter and would love to get some advice on an algorithmic problem I'm facing.
I want to connect my Flutter app to a bluetooth device (that part is done, I am connected already) and send messages on uneven intervals. I have the messages in a list and for each of them I know at what time (milliseconds) I want to send the message.
So suppose the following messages are lined up:
start
at 0msinit_app
at 100msuser_pick_x
at 500msuser_start_x
at 500ms (will be sent after user_pick_x
, order should be guaranteed)interrupt
at 3500msI have found the documentation to create streams, but it always talks about a single interval value. https://dart.dev/articles/libraries/creating-streams.
Ideas:
Duration
objects and work with a custom generator async*
, along with the message string.It would be nice to be able to pause / cancel the stream as well. Which is something that streams can do natively.
I think the easiest is to just emit those messages at the specified intervals. Something like:
Future<void> _wait(int milliseconds) async =>
await Future<void>.delayed(Duration(milliseconds: milliseconds));
Stream<String> generateMessages() async* {
yield 'start';
await _wait(100);
yield 'init_all';
await _wait(400);
yield 'user_pick_x';
yield 'user_start_x';
await _wait(3000);
yield 'interrupt';
}
void main() {
generateMessages().listen((msg) {
print('${DateTime.now()}: $msg');
});
}
which will print:
2021-07-25 10:21:21.429: start
2021-07-25 10:21:21.531: init_all
2021-07-25 10:21:21.934: user_pick_x
2021-07-25 10:21:21.934: user_start_x
2021-07-25 10:21:24.938: interrupt
If you want to make sure that the listener of the stream receives events asynchronously - hence not interfering with the wait milliseconds, you can explicitly use the StreamController
which by default calls the listeners asynchronously (make sure to import dart:async --- dart:io is only used in the example for the sleep
to show that even on a blocking action it will run in parallel with the waiting):
import 'dart:async';
import 'dart:io';
Future<void> _wait(int milliseconds) async {
print('WAIT $milliseconds ms');
await Future<void>.delayed(Duration(milliseconds: milliseconds));
}
Stream<String> generateMessages() {
final controller = StreamController<String>(sync: false);
controller.onListen = () async {
controller.add('start');
await _wait(100);
controller.add('init_all');
await _wait(400);
controller.add('user_pick_x');
controller.add('user_start_x');
await _wait(3000);
controller.add('interrupt');
};
return controller.stream;
}
void main() {
generateMessages().listen((msg) {
sleep(const Duration(milliseconds: 120));
print('${DateTime.now()}: $msg');
});
}