Flutter-流已经使用套接字进行了监听

时间:2019-10-22 16:42:05

标签: sockets flutter stream

我有点迷失了,我使用Streambuilder()函数获取了Esp8266的数据,问题是,每次更换屏幕并弹出屏幕时,都会出现错误:流已经被听过

我读到我应该在广播中使用Streamcontroller。但是我不知道该如何使用或监听套接字的更改。

现在结果是我的Text小部件中没有任何内容。

这是我的代码(简化版,只有一页)

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'dart:io';
import 'dart:async';

void main() async{
  Socket sock = await Socket.connect('192.168.1.24', 80);
runApp(MyApp(sock));
}

class MyApp extends StatelessWidget {
  Socket socket;

  MyApp(Socket s){
    this.socket = s;
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page',
        channel : socket,
      ),

    );
  }
}

class MyHomePage extends StatefulWidget {
  final Socket channel;
  MyHomePage({Key key, this.title, this.channel}) : super(key: key);



  final String title;



  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController _controller = TextEditingController();

  StreamController streamController = new StreamController.broadcast();   
//I have my controller here, but I need it to listen to my widget.channel




  void _togglePower(){
    widget.channel.write("Apero\n");

  }
  /*
  @override
  void dispose(){
    widget.channel.close(); //Faire un flush avant de close.
    super.dispose();
  }*/

  @override
  void dispose(){
    streamController.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {


    return Scaffold(
      appBar: AppBar(

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              child: Text("Testou",
              style: TextStyle(
                color: Colors.amber,
                fontStyle: FontStyle.italic,
                fontSize: 20
              )
            ),
        color: Colors.black,
              onPressed: _togglePower,
            ),


            Form(
              child: TextFormField(
                controller: _controller,
                decoration: InputDecoration(labelText: 'Send a message'),
              ),
            ),
            StreamBuilder(
              stream: streamController.stream,
              builder: (context, snapshot) {
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 24.0),
                  child: Text(snapshot.hasData
                      ? '${String.fromCharCodes(snapshot.data)}'
                      : 'loading'),
                );
              },
            )
          ],
        ),
      ),

    );
  }

}

或者也许有一种方法可以使用widget.channel.listen使其更简单?

感谢您的帮助! 晚上好:)

1 个答案:

答案 0 :(得分:0)

当您单次订阅流上多次调用listen()时,将显示此错误。 我在源代码中找到以下几行。

  • 不允许在单订阅流上收听两次
  • 即使第一个订阅已取消

因此,您需要将套接字更改为BroadcastSteam,在此处保存实例,并且不要多次调用asBroadcastStream()。

静态bcSteam = socket.asBroadcastStream();

bcSteam.listen((event) {
  final data = json.decode(utf8.decode(event));
  handleSocketData(data);
});