I want to create a stream from user input and then have a listener print the stream events. The problem I'm having is that the listener code isn't running.
import 'dart:io';
import 'dart:async';
void main() {
Stream letterStream = LetterGuesser().getStream.asBroadcastStream();
StreamSubscription listener = letterStream.listen((event) {
print(event); // <- this isn't running
});
}
String getLetter() {
bool validLetter;
String userInput;
do {
stdout.write("Enter a letter: ");
userInput = stdin.readLineSync() ?? "";
userInput = userInput.toLowerCase();
validLetter = RegExp(r'^[a-z]$').hasMatch(userInput);
if (!validLetter) print("Please pick a letter from a to z.");
} while (!validLetter);
return userInput;
}
class LetterGuesser {
StreamController<String> _controller = StreamController<String>();
Stream<String> get getStream => _controller.stream;
LetterGuesser() {
do {
final letter = getLetter();
_controller.sink.add(letter);
} while (true);
}
}
CodePudding user response:
void main() {
final letterGuesser = LetterGuesser();
Stream letterStream = letterGuesser.getStream.asBroadcastStream();
StreamSubscription listener = letterStream.listen((event) {
print(event); // <- this isn't running
});
letterGuesser.getUserInput();
}
String getLetter() {
bool validLetter;
String userInput;
do {
stdout.write("Enter a letter: ");
userInput = stdin.readLineSync() ?? "";
userInput = userInput.toLowerCase();
validLetter = RegExp(r'^[a-z]$').hasMatch(userInput);
if (!validLetter) print("Please pick a letter from a to z.");
} while (!validLetter);
return userInput;
}
class LetterGuesser {
StreamController<String> _controller = StreamController<String>(sync: true);
Stream<String> get getStream => _controller.stream;
void getUserInput() {
do {
final letter = getLetter();
_controller.sink.add(letter);
} while (true);
}
}
Explaination
StreamController<String>(sync: true);
add argument sync: true
because stdin.readLineSync
is synchronous. the default StreamController is async. the stream's listeners never get called because the main thread keeps getting blocked by a sync operation.
void getUserInput() {
do {
final letter = getLetter();
_controller.sink.add(letter);
} while (true);
}
move the loop to a method. because if it is in constructor then the program will stay in constructor.
void main() {
final letterGuesser = LetterGuesser();
Stream letterStream = letterGuesser.getStream.asBroadcastStream();
StreamSubscription listener = letterStream.listen((event) {
print(event); // <- this isn't running
});
letterGuesser.getUserInput();
}
add listener to the stream and then start getting input from user.