Flutter 如果StreamBuilder中的流返回null,我必须做什么?
我正在尝试将websocket与此软件包一起使用,一切正常,直到我意识到如果通道第一次无法与服务器连接,则流将为null,我得到以下错误: 对null调用了getter“stream” 我将频道设置为一个单例类,这样我就可以在我的应用程序中的任何地方调用close或add:Flutter 如果StreamBuilder中的流返回null,我必须做什么?,flutter,dart,Flutter,Dart,我正在尝试将websocket与此软件包一起使用,一切正常,直到我意识到如果通道第一次无法与服务器连接,则流将为null,我得到以下错误: 对null调用了getter“stream” 我将频道设置为一个单例类,这样我就可以在我的应用程序中的任何地方调用close或add: class WebSocket { static IOWebSocketChannel channel; static init() async { try { String macAddress
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(),这样通道就可以进行流传输了,但是如果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}' : ''),
);
},
问题是当连接失败时,
channel
为null
,因此您不能执行channel.stream
,而StreamBuilder
不能有流。因此,您可以采取的一种方法是在WebSocket
中有一个Stream
来处理重试操作,当频道
就绪时,将来自channel.Stream
的数据传递到WebSocket
流
这就是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();
}
@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...');
},
),
),
);
}
这将是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();
}
如果频道无法连接,您想做什么?只是显示错误,尝试自动重新连接或添加按钮尝试重新连接?我想自动重新连接我已尝试为通道检查null,但问题是IOWebSocketChannel。connect()仍然返回IOWebSocketChannel,即使它无法连接,因此我无法检查它以调用重新连接通道。但是,您的工具很棒。我已经解决了我的问题,虽然它有点不灵活。感谢您的帮助。我正在检查WebSocket的通道变量是否为null,而不是connect()返回的通道。我假设如果它不能连接,它会抛出一个异常,这样通道就不会被分配。即使它没有抛出异常,您也可以检查通道==null | |!channel.isConnected()或任何您必须知道它是否已连接的方法在tryToConnect中,通道是从connect分配的,因此它无法调用重新连接,因为它不能为null,它也不会引发异常,我已经尝试过了。对不起,我不能接受你的道歉,请投票给伟大的工具。谢谢你没问题,我只是想知道这是怎么回事。如果connect返回一个对象但未连接,您如何知道该对象未连接?