动态更改 Streambuilder 中的流
Change a stream in Streambuilder dynamically
我正在使用 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();
}
});
},
),
(...)
您可以不使用 StreamController 而是在执行过滤器时保留对 Stream 的引用,例如:
Stream? filterStream;
String? filterValue;
// you can create a method that performs the filtering for you, such as:
void resetStreamWithNameFilter() {
setState(() {
// return all products if your filter is empty
if (filter.isEmpty) {
filterStream = FirebaseFirestore.instance.collection('Producto').snapshots();
return;
}
// if the filter is not empty, then filter by that field 'nombre'
valueStream = FirebaseFirestore.instance.collection('team').where('nombre', isEqualTo: filter).snapshots();
});
}
那么在你的构建方法中,这将是你调用的第一个方法;还使用新创建的 filterStream 字段,如:
@override
Widget build(BuildContext context) {
// call it initially, to reset the stream
resetStreamWithNameFilter();
return StreamBuilder(
stream: filterStream,
builder: (context, snapshot) {
// do what you want to do here, but trigger the filter accordingly
List<QueryDocumentSnapshot> docs = (snapshot.data as QuerySnapshot).docs;
return Column(
children: [
Text(docs.length.toString()),
TextButton(
onPressed: () {
// for example, filter by all products named 'camisa'
filterString = 'camisa';
// then, execute the resetStreamWithNameFilter
resetStreamWithNameFilter();
}
)
]
);
}
);
}
我创建了一个 Gist 这样你就可以理解了。 运行 在 DartPad 上查看它。
我正在使用 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();
}
});
},
),
(...)
您可以不使用 StreamController 而是在执行过滤器时保留对 Stream 的引用,例如:
Stream? filterStream;
String? filterValue;
// you can create a method that performs the filtering for you, such as:
void resetStreamWithNameFilter() {
setState(() {
// return all products if your filter is empty
if (filter.isEmpty) {
filterStream = FirebaseFirestore.instance.collection('Producto').snapshots();
return;
}
// if the filter is not empty, then filter by that field 'nombre'
valueStream = FirebaseFirestore.instance.collection('team').where('nombre', isEqualTo: filter).snapshots();
});
}
那么在你的构建方法中,这将是你调用的第一个方法;还使用新创建的 filterStream 字段,如:
@override
Widget build(BuildContext context) {
// call it initially, to reset the stream
resetStreamWithNameFilter();
return StreamBuilder(
stream: filterStream,
builder: (context, snapshot) {
// do what you want to do here, but trigger the filter accordingly
List<QueryDocumentSnapshot> docs = (snapshot.data as QuerySnapshot).docs;
return Column(
children: [
Text(docs.length.toString()),
TextButton(
onPressed: () {
// for example, filter by all products named 'camisa'
filterString = 'camisa';
// then, execute the resetStreamWithNameFilter
resetStreamWithNameFilter();
}
)
]
);
}
);
}
我创建了一个 Gist 这样你就可以理解了。 运行 在 DartPad 上查看它。