首页 > 解决方案 > StreamProvider 和 TCP 套接字

问题描述

我编写了一个单页桌面应用程序来与 TCP Server 通信。

在我的代码中,我使用 Socket.listen() 方法来接收数据,它是可以的。

我试图将其转换为 StreamProvider[Riverpod] 但失败了。

你能建议我正确的方法吗?
附带说明:我不是经验丰富的颤振开发人员,只是尝试学习:)

我在下面添加了代码块以及完整的代码。

完整代码:https ://gist.github.com/sphinxlikee/3cbfa47817a5187c7b67905028674041

用户界面:

在此处输入图像描述

工作代码;

  Future<void> createConnection() async {
    try {
      _socket = await Socket.connect(serverAddress, serverPort);
      _changeConnectionState();
    } catch (e) {
      print('connection has an error and socket is null.');
      print(e);
      return;
    }

    listenSocket();
  }

  void listenSocket() {
    _socket.listen(
      (event) {
        _getData(String.fromCharCodes(event));
        print('received: $receivedData');

        if (!_dataReceived) {
          _changeDataReceivedState();
        }
      },
    )
      ..onDone(
        () {
          _changeConnectionState();
          _streamDone();
          print('socket is closed');
        },
      )
      ..onError(
        (error, stackTrace) {
          print('$error');
        },
      );
  }

工作代码 - UI 端

class ReceivedData extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final receivedData = watch(tcpClientProvider).receivedData;
    return Text('Received data: $receivedData');
  }
}

对于我尝试过的 StreamProvider,

 Future<void> createConnection() async {
    try {
      _socket = await Socket.connect(serverAddress, serverPort);
      streamController.sink.add(_socket.listen((event) => String.fromCharCodes(event)));
      _changeConnectionState();
    } catch (e) {
      print('connection has an error and socket is null.');
      print(e);
      return;
    }

  }

StreamProvider - UI 端

final streamProvider = StreamProvider.autoDispose(
  (ref) async* {
    await for (final value in ref.watch(tcpClientProvider).streamController.stream) {
      yield value;
    }
  },
);

class ReceivedDataWithProvider extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    AsyncValue receivedData = watch(streamProvider);

    return receivedData.when(
      data: (data) => Text('Received data: $data'),
      loading: () => const CircularProgressIndicator(),
      error: (err, stack) => Text('error'),
    );
  }
}

标签: fluttersocketstcpriverpod

解决方案


Socket 实现了 Stream,所以你可以写:

final streamProvider = StreamProvider.autoDispose<Uint8List>((ref) {
  return ref.watch(tcpClientProvider)._socket;
});

如果您仍想添加一个侦听器,如果需要,拥有一个也没有什么坏处:

final streamProvider = StreamProvider.autoDispose<Uint8List>((ref) {
  final client = ref.watch(tcpClientProvider);

  return client._socket
    ..listen(
      (event) {},
    ).onDone(
      () {
        client
          .._changeConnectionState()
          .._streamDone();
        print('socket is closed');
      },
    );
});

推荐阅读