我在我的 Stateful Widget 中使用了一个切换开关按钮,它设置了一些布尔变量状态是 Builder 是有条件地呈现还是 StreamBuilder
Expanded(
child: Padding(
padding:
const EdgeInsets.fromLTRB(10.0, 32.0, 10.0, 70.0),
child: (showPrivate == true && showPublic == false)
? Builder(
key: Key("private"),
builder: (context) {
if (products.length != 0 &&
products.length != null)
return ListView.builder(
scrollDirection: Axis.vertical,
itemCount: products.length,
itemBuilder: (context, i) {
// ListProduct gets product from map
String key = products.keys.elementAt(i);
if (products[key].isAmount != "0")
return ListProduct(
products[key], false);
else
return SizedBox();
},
);
else
return Center(
child: Text("Empty!"),
);
})
: (showPrivate == false && showPublic == true)
? Expanded(
child: StreamBuilder(
stream: streamSocket.getResponse,
builder: (context,
AsyncSnapshot<String> snapshot) {
if (snapshot.data != null) {
return Container(
child: Text(snapshot.data),
);
} else {
return ListView.builder(
scrollDirection: Axis.vertical,
itemCount: products.length,
itemBuilder: (context, i) {
// ListProduct gets product from map
String key =
products.keys.elementAt(i);
if (products[key].isAmount != "0")
return ListProduct(
products[key], false);
else
return SizedBox();
},
);
}
},
),
)
: Text("")),)
我已经构建了这个自定义流套接字控制器
class StreamSocket {
var _socketResponse = StreamController<String>();
void Function(String) get addResponse => _socketResponse.sink.add;
Stream<String> get getResponse => _socketResponse.stream;
void connectToWebSocket() async {
try {
IO.Socket socket = IO.io(
"http://localhost:3001/",
IO.OptionBuilder()
.setTransports(['websocket'])
.disableAutoConnect()
.build());
socket.connect();
} catch (err) {
print("Error: $err");
}
}
void dispose() {
_socketResponse.close();
}
}
当我切换 StreamBuilder 超过 2 次并输出此错误时发生错误:
Bad state: Stream has already been listened to.
The relevant error-causing widget was
Expanded
答案 0 :(得分:0)
您需要在小部件中定义一个流,将其分配给 initState 中的 StreamSocket 流并在 StreamBuilder 中使用它
代码如下:
StreamSocket streamSocket;
Stream<String> stream;
@override
void initState() {
streamSocket = StreamSocket();
stream = streamSocket.getResponse;
super.initState();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: Padding(
padding:
const EdgeInsets.fromLTRB(10.0, 32.0, 10.0, 70.0),
child: (showPrivate == true && showPublic == false)
? Builder(
key: Key("private"),
builder: (context) {
if (products.length != 0 &&
products.length != null)
return ListView.builder(
scrollDirection: Axis.vertical,
itemCount: products.length,
itemBuilder: (context, i) {
// ListProduct gets product from map
String key = products.keys.elementAt(i);
if (products[key].isAmount != "0")
return ListProduct(
products[key], false);
else
return SizedBox();
},
);
else
return Center(
child: Text("Empty!"),
);
})
: (showPrivate == false && showPublic == true)
? Expanded(
child: StreamBuilder(
stream: stream,
builder: (context,
AsyncSnapshot<String> snapshot) {
if (snapshot.data != null) {
return Container(
child: Text(snapshot.data),
);
} else {
return ListView.builder(
scrollDirection: Axis.vertical,
itemCount: products.length,
itemBuilder: (context, i) {
// ListProduct gets product from map
String key =
products.keys.elementAt(i);
if (products[key].isAmount != "0")
return ListProduct(
products[key], false);
else
return SizedBox();
},
);
}
},
),
)
: Text("")),);
}