首页 > 解决方案 > Flutter `socket_io_client` 将 socket.on(event, data) 转换为流并在动态生成的流构建器中使用

问题描述

我有一个人列表,每个人都有自己的套接字连接。我正在使用 aListBuilder为它们生成小部件列表,但我希望这些小部件中的每一个都监听此人的套接字连接是否已收到来自服务器的事件并相应地更新。我已经尝试了所有可以在网上找到的方法,但仍然找不到解决方案。

这是我尝试使用下面发布的解决方案之一

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:socket_io_client/socket_io_client.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Person> sockets = [
    Person(
        name: 'Jon',
        socket: io('http://localhost:3000', {
          'transports': ['websocket'],
          'autoConnect': false
        }),
        controller: StreamController<String>()),
    Person(
        name: 'Tim',
        socket: io('http://localhost:3000', {
          'transports': ['websocket'],
          'autoConnect': false
        }),
        controller: StreamController<String>()),
    Person(
        name: 'Bob',
        socket: io('http://localhost:3000', {
          'transports': ['websocket'],
          'autoConnect': false
        }),
        controller: StreamController<String>()),
  ];

// function to sink the data
  void sinkToController(data, Person person) {
    var message = '$data';
    person.controller.sink.add(message);
  }

  void streamPerson(Person person) {
    person.socket.connect();
    person.socket.on('connect', (data) {
      print('connected');
      person.socket.on('serverMessage', (data) {
        print('$data');
        sinkToController(data, person);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Socket test app"),
      ),
      body: Container(
          child: ListView.builder(
              itemCount: 3,
              itemBuilder: (context, index) {
                streamPerson(sockets[index]);

                return GestureDetector(
                  onTap: () => sockets[index].socket.emit('msg', 'this is me: ${sockets[index].name}'),
                  child: Container(
                    height: 300,
                    width: 350,
                    child: Column(
                      children: [
                        Text(sockets[index].name),
                        StreamBuilder<String>(
                          initialData: 'initial',
                          stream: sockets[index].controller.stream,
                          builder: (context, snapshot) {
                            return Text('${snapshot.data}');
                          },
                        )
                      ],
                    ),
                  ),
                );
              })),
    );
  }
}

class Person {
  String name;
  Socket socket;
  StreamController<String> controller;

  Person({this.name, this.socket, this.controller});
}

但是,这不起作用,所以我希望是否有办法将 socket.on('event') 动态转换为流并在生成的流构建器中使用它。

结果是

一个列表构建器,每个人**应该**都有自己的数据流和他们自己的名字

先感谢您

标签: socketsflutterdartsocket.iostream-builder

解决方案


您应该使用 StreamController 为每个用户创建一个流。您可以在此处阅读更多相关信息:https ://dart.dev/articles/libraries/creating-streams#using-a-streamcontroller

^^^已编辑以在上面添加更好的答案

下面是我对发电机的初步尝试。不过,它可能行不通。

  Stream userToLocationStream(User user) async* {
    user.websocket.on('connect', (_) {
      user.websocket.on('LocationChange', (data) {
        yield data;
      });
    });
  }

也许如果您决定遵循这条生成器路线而不是 StreamController,我关于生成器的演讲可能会有所帮助:https ://youtu.be/vPHxckiSmKY?t=4112


推荐阅读