流侦听器和 streamController "talking" 异步未按预期工作

Stream listener and streamController "talking" asynchronously not working as expected

我试图了解如何从 Template flutter 代码开始使用 Streams。

我得到的输出是

I/flutter (32673): MyApp build executing
I/flutter (32673): HomePage constructor executing
I/flutter (32673): MyHomePage createState() _MyHomePageState executing
I/flutter (32673): _MyHomePageState constructor executing
I/flutter (32673): Awaiting anxiously for the speaker to start speaking!
I/flutter (32673): _MyHomePageState build() executing
I/flutter (32673): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter (32673): _MyHomePageState setState() executing
I/flutter (32673): _MyHomePageState build() executing
I/flutter (32673): _MyHomePageState /  floatingActionButton: onPressed executing

我期待这样的事情:

I/flutter (32673): MyApp build executing
I/flutter (32673): HomePage constructor executing
I/flutter (32673): MyHomePage createState() _MyHomePageState executing
I/flutter (32673): _MyHomePageState constructor executing
I/flutter (32673): Awaiting anxiously for the speaker to start speaking!
I/flutter (32673): _MyHomePageState build() executing
I/flutter (32673): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter (32673): _MyHomePageState setState() executing
I/flutter (32673): _MyHomePageState build() executing
I/flutter (32673): Topic1 loud and clear
I/flutter (32673): Topic2 loud and clear
I/flutter (32673): Great topic1. APPLAUSE!!!!
I/flutter (32673): Topic3 loud and clear
I/flutter (32673): Topic4 loud and clear
I/flutter (32673): Topic5 loud and clear
I/flutter (32673): Great topic2. APPLAUSE!!!
I/flutter (32673): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter (32673): Topic6 loud and clear
I/flutter (32673): Great topic3. APPLAUSE!!!

这是我用来理解 Streams 的代码...我做错了什么?

import 'package:flutter/material.dart';
import 'package:streams/speaker.dart';
import 'package:streams/listener1.dart';

void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print ('MyApp build executing');
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  final String title;
  MyHomePage({Key? key, required this.title }) : super(key: key) {
    print('HomePage constructor executing');
  }
  @override
  _MyHomePageState createState() {
    print('MyHomePage createState() _MyHomePageState executing');
    return _MyHomePageState();
  }
}
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  _MyHomePageState() : super(){
    print('_MyHomePageState constructor executing');
    var listener1 = NumberListener();
    var speaker = NumberSpeaker();
    listener1.listen();                      // Start listening
    speaker.speak();                         // Start speaking
  }
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    print('_MyHomePageState build() executing');
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          print('_MyHomePageState /  floatingActionButton: onPressed executing');
          _incrementCounter();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

导入'package:streams/speaker.dart';

import 'dart:async';
class NumberSpeaker {
  final StreamController _streamController = StreamController<int>();
  Stream<int>? get stream {
    return _streamController.stream as Stream<int>;
  }
  int _topicNumber = 1;
  int _numberOfTopics = 20;
  speak() async* {
    while (_topicNumber != _numberOfTopics) {               //Speak all 20 topics
      yield _topicNumber;                                   //yield 1 topic at a time
      print('Topic$_topicNumber loud and clear');
      _topicNumber = _topicNumber + 1;
    }
    _streamController.close();
  }
}

导入'package:streams/listener1.dart';

import 'dart:async';
import 'package:streams/speaker.dart';
class NumberListener {
  final speakerStream = NumberSpeaker().stream;
  Future<void> listen() async {
    print('Awaiting anxiously for the speaker to start speaking!');
    await for (var topic in speakerStream!) {                         //wait for the speaker to start
      var wholeSpeach = speakerStream!.listen(
        (topic) {
          print('Great topic$topic. APPLAUSE!!!!');
        },
        onError: (err) {
          print('Error: $err');
        },
        cancelOnError: false,
        onDone: () {
          print('Thunderous  APPLAUSE!!!!!');
        }
      );
    }
  }
}
final speakerStream = NumberSpeaker().stream;

此行连接到 NumberSpeakernew 实例。你有两个 NumberSpeaker 个实例,一个你正在听,另一个正在说话。

监听器应该将要监听的流作为构造函数参数,这样您就可以传入您拥有的实际扬声器实例的流。

例如:

class NumberListener {
  final Stream<int> speakerStream;

  NumberListener(this.speakerStream);

然后当您创建它们时:

var speaker = NumberSpeaker();
var listener1 = NumberListener(speaker.stream);

listener1.listen();
speaker.speak();

出于某种原因,您从 getter 返回一个 nullable 流。解决这个问题。返回一个 nullable 流没有意义,它应该只是一个流。

此外,请考虑一下 psink 在评论中写的内容。

在@nvoigt 和@pskink 的大力帮助下,我获得了想要的结果……以及更多!

现在,我可以拥有一个响应式应用程序,同时在后台执行异步代码!现在我可以离开寺庙了!

希望这对其他 ForTran/CoBOL 像我这样的老朋友有帮助。 项目托管于此:https://github.com/SpeedyVV/streams.git

Launching lib\main.dart on Android SDK built for x86 in debug mode...
Running Gradle task 'assembleDebug'...
√  Built build\app\outputs\flutter-apk\app-debug.apk.
Installing build\app\outputs\flutter-apk\app.apk...
Debug service listening on ws://127.0.0.1:62722/4AqZ6OkPT3o=/ws
Syncing files to device Android SDK built for x86...
D/EGL_emulation( 4966): eglMakeCurrent: 0xde1cce80: ver 2 0 (tinfo 0xd61aa220)
D/eglCodecCommon( 4966): setVertexArrayObject: set vao to 0 (0) 1 0
I/flutter ( 4966): MyApp build executing
I/flutter ( 4966): HomePage constructor executing
I/flutter ( 4966): MyHomePage createState() _MyHomePageState executing
I/flutter ( 4966): _MyHomePageState constructor executing
I/flutter ( 4966): Listener: Awaiting anxiously for the speaker to start speaking!
I/flutter ( 4966): Speaker: Oh, there is someone listening!
I/flutter ( 4966): Speaker: Topic1 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Listener: Great topic1. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic2 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic2. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic3 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic3. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic4 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic4. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic5 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic5. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic6 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic6. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic7 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic7. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic8 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic8. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): Speaker: Topic9 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic9. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic10 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic10. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic11 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic11. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic12 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic12. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic13 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic13. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic14 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic14. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic15 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic15. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic16 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic16. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic17 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic17. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic18 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic18. APPLAUSE!!!!
I/flutter ( 4966): Speaker: Topic19 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic19. APPLAUSE!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): Speaker: Topic20 loud and clear
I/flutter ( 4966): Speaker: Waiting 1/4 second for applause.
I/flutter ( 4966): Listener: Great topic20. APPLAUSE!!!!
I/flutter ( 4966): Speaker: And that is all I have to say.
I/flutter ( 4966): Thank you for listening.
I/flutter ( 4966): Listener: Thunderous  APPLAUSE!!!!!
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
I/flutter ( 4966): _MyHomePageState /  floatingActionButton: onPressed executing
I/flutter ( 4966): _MyHomePageState setState() executing
I/flutter ( 4966): _MyHomePageState build() executing
Application finished.

这是根据给定答案的新代码

main.dart

  _MyHomePageState() : super(){
    print('_MyHomePageState constructor executing');

    var speaker = NumberSpeaker();
    var listener1 = NumberListener(speaker.stream);

    listener1.listen();
    speaker.speak();
  }

listener1.dart

class NumberListener {
  final Stream<int> speakerStream;
  NumberListener(this.speakerStream);

  //final speakerStream = NumberSpeaker().stream;

  void listen()  {
    print('Awaiting anxiously for the speaker to start speaking!');
    //await for (var topic in speakerStream!) {
    var wholeSpeach = speakerStream.listen(
      (topic) {
        print('Great topic$topic. APPLAUSE!!!!');
      },
      onError: (err) {
        print('Error: $err');
      },
      cancelOnError: false,
      onDone: () {
        print('Thunderous  APPLAUSE!!!!!');
      }
    );
  }
}

speaker.dart

我试图了解如何从 Template flutter 代码开始使用 Streams。

import 'dart:async';

class NumberSpeaker {

  final StreamController _streamController = StreamController<int>();

  Stream<int> get stream {
    return _streamController.stream as Stream<int>;
  }

  int _topicNumber = 1;
  int _numberOfTopics = 20;

  speak() async {
    print('Oh, there is someone listening!');
    while (_topicNumber <= _numberOfTopics) {
      _streamController.add(_topicNumber);
      Future.delayed(Duration(seconds: 3));
      print('Topic$_topicNumber loud and clear');
      _topicNumber = _topicNumber + 1;
    }
    _streamController.close();
  }
}