【问题标题】:"Bad state: Stream has already been listened to" occurs when I visit screen multiple times当我多次访问屏幕时出现“状态不佳:流已被收听”
【发布时间】:2021-01-26 09:38:22
【问题描述】:

我正在使用flutter_bluetooth_serial 库,并且在initState() 函数中我正在使用listen 来调用一个函数。当应用程序最初启动时它工作正常,但是当我在应用程序上第二次访问此屏幕时,我得到一个红色屏幕,上面写着“状态不佳:流已被收听”。

我是 Flutter 新手,所以请提供可以帮助我解决此问题的确切代码。

 @override
  void initState() {
    super.initState();

    widget.connection.input.listen(_onDataReceived).onDone(() {
      // Example: Detect which side closed the connection
      // There should be `isDisconnecting` flag to show are we are (locally)
      // in middle of disconnecting process, should be set before calling
      // `dispose`, `finish` or `close`, which all causes to disconnect.
      // If we except the disconnection, `onDone` should be fired as result.
      // If we didn't except this (no flag set), it means closing by remote.
      if (isDisconnecting) {
        print('Disconnecting locally!');
      } else {
        print('Disconnected remotely!');
      }
      if (this.mounted) {
        setState(() {});
      }
    });
  }

【问题讨论】:

    标签: flutter dart bluetooth flutter-dependencies android-bluetooth


    【解决方案1】:

    尝试覆盖状态的dispose() 方法并取消其中的订阅。为此,您需要将订阅保存在一个变量中:

      StreamSubscription _subscription;
    
      @override
      void initState() {
        super.initState();
        _subscription = widget.connection.input.listen(_onDataReceived, onDone: () {
          ...
        });
      }
    
      override
      void dispose() {
        _subscription.cancel();
        super.dispose();
      }
    

    编辑

    如果您需要在整个应用程序中多次订阅connection.input - 您可以将其转换为广播流并订阅它。它应该有帮助。像这样:

    final broadcastInput = connection.input.asBroadcastStream();
    

    但如果您只需要在此小部件中使用连接,我建议您将其保持在状态(而不是小部件)并在处置时将其关闭。这将是更好的生命周期控制解决方案。

      BluetoothConnection _connection;
    
      @override
      void initState() {
        super.initState();
        _initConnection();
      }
    
      Future<void> _initConnection() async {
        _connection = await BluetoothConnection.toAddress(address);
        /// Here you can subscribe for _connection.input
        ...
      }
    
      @override
      void dispose() {
        connection;
        super.dispose();
      }
    

    【讨论】:

    • 还是同样的问题。没有区别
    • 另一件要提的事情是,我使用 android 后退按钮向后导航以访问同一页面。还好吗?
    • @user12326 我编辑了我的答案,看看吧。
    猜你喜欢
    • 2021-07-04
    • 2021-02-26
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2021-12-26
    • 2018-12-26
    • 2019-03-23
    • 2020-03-08
    相关资源
    最近更新 更多