gpt4 book ai didi

flutter - 如果 StreamBuilder 中的流返回 null,我该怎么办?

转载 作者:行者123 更新时间:2023-12-03 04:27:34 25 4
gpt4 key购买 nike

我正在尝试将 websocket 与此包一起使用 websocket一切都很好,直到我意识到如果 channel 第一次无法与服务器连接,流将为空,我收到此错误:

The getter 'stream' was called on null



我将 channel 设为单例类,因此我可以在我的应用程序中调用 close 或添加任何我想要的地方:
class WebSocket {
static IOWebSocketChannel channel;
static init() async {
try {
String macAddress = await getMacAddress();
channel = IOWebSocketChannel.connect("ws://172.16.0.39:8001/ws/fsmart-door/$macAddress");
} catch (e) {
debugPrint(e.toString());
}
}
}

我在 main 中调用 Websocket.init() 以便 channel 准备好流,但如果 IOWebSocketChannel.connect 无法连接,应用程序也会卡住。

这是我的 StreamBuilder:
StreamBuilder(
stream: WebSocket.channel.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {

}
return Padding(
padding: const EdgeInsets.symmetric(vertical: 24.0),
child: Text(snapshot.hasData ? '${snapshot.data}' : ''),
);
},

最佳答案

问题是当连接失败时,channelnull所以你不能做channel.streamStreamBuilder不能有 Stream .因此,您可以采取的一种方法是使用 StreamWebSocket处理重试和何时 channel准备好了,传递来自channel.stream的数据到WebSocket Stream .

这就是WebSocket :

class WebSocket {
static WebSocket _instance;
final _streamController = StreamController.broadcast();
IOWebSocketChannel channel;

static WebSocket get instance {
if (_instance == null) {
_instance = WebSocket();
}
return _instance;
}

Stream get channelStream => _streamController.stream;

Future init(int retries) async {
if (channel == null) {
await _tryToConnect(retries);
if (channel != null) {
_streamController.sink.add(null);
channel.stream.listen((value) {
_streamController.sink.add(value);
});
} else {
_streamController.sink.addError("Could not connect");
}
}
}

Future _tryToConnect(int retries) async {
if (channel == null) {
try {
String macAddress = await getMacAddress();
// This is to throw exception if it can't connect (https://github.com/dart-lang/web_socket_channel/issues/38#issuecomment-450383558)
final socket = await WebSocket.connect(
"ws://172.16.0.39:8001/ws/fsmart-door/$macAddress")
.timeout(_webSocketConnectionTimeout);
channel = IOWebSocketChannel(socket);
} catch (e) {
debugPrint(e.toString());
}
if (channel == null && retries > 0) {
_streamController.sink.addError("Retries left: ${retries - 1}");
await _tryToConnect(retries - 1);
}
}
}

void close() => _streamController.close();
}

这将是 StreamBuilder :
StreamBuilder(
stream: WebSocket.instance.channelStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Data: ${snapshot.data}');
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Text('Loading...');
},
)

如果您想对此解决方案进行快速测试,请替换 try 中的两行 catch , 为了这:
await Future.delayed(Duration(seconds: 3));
if (retries == 2) channel = IOWebSocketChannel();

使用这个 IOWebSocketChannel
class IOWebSocketChannel {
var _streamController = StreamController<String>.broadcast();

IOWebSocketChannel() {
init();
}

Stream get stream => _streamController.stream;

Future init() async {
await Future.delayed(Duration(seconds: 3));
_streamController.sink.add("1");
await Future.delayed(Duration(seconds: 3));
_streamController.sink.add("2");
}

void close() => _streamController.close();
}

并在 StatefulWidget 中使用此示例:
@override
void initState() {
super.initState();
WebSocket.instance.init(5);
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: StreamBuilder(
stream: WebSocket.instance.channelStream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Data: ${snapshot.data}');
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
return Text('Loading...');
},
),
),
);
}

关于flutter - 如果 StreamBuilder 中的流返回 null,我该怎么办?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58443552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com