flutter - StreamProvider 和 TCP 套接字
问题描述
我编写了一个单页桌面应用程序来与 TCP Server 通信。
在我的代码中,我使用 Socket.listen() 方法来接收数据,它是可以的。
- 我使用单一订阅,这对我来说已经足够了。
我试图将其转换为 StreamProvider[Riverpod] 但失败了。
- 我使用了 StreamController() 然后我得到了不好的状态。
- 我使用了 StreamController.broadcast() 并且无法从套接字获取数据
你能建议我正确的方法吗?
附带说明:我不是经验丰富的颤振开发人员,只是尝试学习:)
我在下面添加了代码块以及完整的代码。
完整代码: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'),
);
}
}
解决方案
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');
},
);
});
推荐阅读
- ios - 在 iOS 中切换 RTL 时,UIAlertController 未在中心显示文本
- javascript - 如何创建切换导航栏以与 redux thunk 做出反应
- haskell - 尝试在 Nixos 上使用堆栈编译静态可执行文件时出现链接器错误
- android - Viewpager 在 OnePlus 5T 设备中无法正常滑动
- r - 运行 qhpvt 的时间范围
- c - While循环的参数内的逗号
- gremlin - Gremlin 遍历膨胀 (OLTP)
- php - 如何在 symfony 中找到数组的大小
- c - C 指针 - 从绝对地址读取值与 AddressOf 运算符 (&)
- amazon-web-services - Terraform:为多个客户端部署相同的 Web 应用程序