Home > database >  Dart: Creating a stream of keyboard input
Dart: Creating a stream of keyboard input

Time:12-21

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.

  •  Tags:  
  • dart
  • Related