动态更改 Streambuilder 中的流
我正在使用 StreamBuilder 在列表中显示 Firebase 中的一组元素。问题是我需要过滤和更新该列表,更改来自 Streambuilder 的流。我不知道谁能做到这一点。我读到了有关 Streamcontroller 的内容,并尝试使用它,但它抛出了一个错误(“StateError(错误状态:在执行 addStream 时无法添加新事件)”)。 拜托,我不知道该怎么办:( 太感谢了!
这是代码的重要部分:
class _widget_productosState extends State<widget_productos> {
final User? usuario = FirebaseAuth.instance.currentUser;
final firestoreInstance = FirebaseFirestore.instance;
List<dynamic> lista_alergenos = [];
var nombre_filtro = TextEditingController();
var nombre = '';
Stream<QuerySnapshot> stream_datos = FirebaseFirestore.instance.collection('Producto').snapshots();
StreamController<QuerySnapshot> controller = StreamController<QuerySnapshot>.broadcast();
@override
void initState() {
super.initState();
stream_datos.forEach((element) {
controller.add(element);
});
}
@override
Widget build(BuildContext context) {
List<String> filtro_alergenos = [];
return
SafeArea(child:
Scaffold(
backgroundColor: Color.fromARGB(255, 239, 241, 245),
body: StreamBuilder(
stream: controller.stream,//stream_datos, //nombre == '' ? firestoreInstance.collection('Producto').snapshots() : firestoreInstance.collection('Producto').where('nombre', isEqualTo: nombre).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return new Center(child: new CircularProgressIndicator());
}
return
Stack(children: [
Column(children:[
Container(
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(1.0),
border: Border.all(
color: Colors.grey.withOpacity(0.5), width: 1.0),
color: Color.fromARGB(255, 255, 255, 255)),
child: Row(
children: [
IconButton(
(...)
),
onPressed: () {
showDialog(
context: context,
builder: (_) =>mostrar_filtros(filtro_alergenos)
);
},
),
Expanded(
(...)
),
IconButton(
(...)
),
onPressed: () {
setState(() {
nombre = nombre_filtro.text;
if(nombre==''){
controller.stream.drain();
setState(() {
controller.addStream(stream_datos);
});
//stream_datos = firestoreInstance.collection('Producto').where('nombre', isEqualTo: nombre).snapshots();
}else{
stream_datos = firestoreInstance.collection('Producto').where('nombre', isEqualTo: nombre).snapshots();
controller.stream.drain();
controller.addStream(stream_datos);
setState(() {
print("ey");
});
//stream_datos = firestoreInstance.collection('Producto').snapshots();
}
});
},
),
(...)
I'm using StreamBuilder to show a group of elements from Firebase in a list. The problem is that I need to filter and update that list changing the stream from Streambuilder. I don't know who can I do that. I read about Streamcontroller and I tried to use it but it throws me an error ("StateError (Bad state: Cannot add new events while doing an addStream)").
Please, I don't know what to do :(
Thank you so much!
Here is the important parts of the code:
class _widget_productosState extends State<widget_productos> {
final User? usuario = FirebaseAuth.instance.currentUser;
final firestoreInstance = FirebaseFirestore.instance;
List<dynamic> lista_alergenos = [];
var nombre_filtro = TextEditingController();
var nombre = '';
Stream<QuerySnapshot> stream_datos = FirebaseFirestore.instance.collection('Producto').snapshots();
StreamController<QuerySnapshot> controller = StreamController<QuerySnapshot>.broadcast();
@override
void initState() {
super.initState();
stream_datos.forEach((element) {
controller.add(element);
});
}
@override
Widget build(BuildContext context) {
List<String> filtro_alergenos = [];
return
SafeArea(child:
Scaffold(
backgroundColor: Color.fromARGB(255, 239, 241, 245),
body: StreamBuilder(
stream: controller.stream,//stream_datos, //nombre == '' ? firestoreInstance.collection('Producto').snapshots() : firestoreInstance.collection('Producto').where('nombre', isEqualTo: nombre).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return new Center(child: new CircularProgressIndicator());
}
return
Stack(children: [
Column(children:[
Container(
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(1.0),
border: Border.all(
color: Colors.grey.withOpacity(0.5), width: 1.0),
color: Color.fromARGB(255, 255, 255, 255)),
child: Row(
children: [
IconButton(
(...)
),
onPressed: () {
showDialog(
context: context,
builder: (_) =>mostrar_filtros(filtro_alergenos)
);
},
),
Expanded(
(...)
),
IconButton(
(...)
),
onPressed: () {
setState(() {
nombre = nombre_filtro.text;
if(nombre==''){
controller.stream.drain();
setState(() {
controller.addStream(stream_datos);
});
//stream_datos = firestoreInstance.collection('Producto').where('nombre', isEqualTo: nombre).snapshots();
}else{
stream_datos = firestoreInstance.collection('Producto').where('nombre', isEqualTo: nombre).snapshots();
controller.stream.drain();
controller.addStream(stream_datos);
setState(() {
print("ey");
});
//stream_datos = firestoreInstance.collection('Producto').snapshots();
}
});
},
),
(...)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以通过不使用 StreamController 来做到这一点,而是在执行过滤器时保留对 Stream 的引用,例如:
然后在您的构建方法中,这将是您调用的第一个方法;还可以使用新创建的 filterStream 字段,如下所示:
我创建了一个 Gist 这样你就明白了。在 DartPad 上运行并检查一下。
You can do that by not using the StreamController and instead hold a reference to the Stream while you do your filter, such as:
Then in your build method, this would be the first method you call; also use the newly created filterStream field, as in:
I created a Gist so you can get the idea. Run it on DartPad and check it out.