[英]Bad state: Snapshot has neither data nor error in flutter when using StreamBuilder and Firestore
我正在将 Firestore 中的数据添加到Stream
中的StreamBuilder
,但出现以下错误:
发生异常。 StateError (Bad state: Snapshot has neither data nor error
我的代码。
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
AppState? estado;
static String? userID = FirebaseAuth.instance.currentUser?.uid;
static final userColeccion = FirebaseFirestore.instance.collection("users");
var groupfav = ' ';
Stream<QuerySnapshot>? taskGroup;
@override
void initState() {
super.initState();
getGroupFavData();
}
void getGroupFavData() async {
var groupFavData = await userColeccion.doc("$userID").get();
var groupfav = groupFavData.data()!['groupfav'];
taskGroup = FirebaseFirestore.instance
.collection("groups")
.doc(groupfav) // pass the obtained value
.collection("task")
.snapshots();
}
@override
Widget build(BuildContext context) {
estado = Provider.of<AppState>(context, listen: true);
return Scaffold(
appBar: AppBar(
title: const Text("Home"),
automaticallyImplyLeading: false,
),
body: StreamBuilder(
stream: taskGroup,
builder: (
BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot,
) {
if (snapshot.hasError) {
return const Text("error");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
var data = snapshot.requireData;
return ListView.builder(
itemCount: data.size,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text("${data.docs[index]['titulo']}"),
subtitle: Text("${data.docs[index]['contenido']}"),
onTap: () {},
trailing: IconButton(
icon: const Icon(Icons.delete),
color: Colors.red[200],
onPressed: () {},
),
),
);
},
);
},
),
);
}
}
好的,看看你的问题,我明白了 1) 你需要在开始收听该文档之前获取文档的数据,这是正常的,所以你想先调用集合,获取文档,然后监听名为task的文档集合,这是有道理的。 您的问题仍然是异步问题。 该应用程序正在重建 stream,但仍未到达; 你必须确定事物的顺序。
然后你需要稍微改变一下并执行以下操作:
选项 #1 :a) 使用FutureBuilder :这将允许您根据用户 ID 进行异步调用以获取文档名称 b) 在您获得与该用户关联的文档后,您想要收听stream该文档中称为任务的集合。 在那里你可以连接StreamBuilder 。
选项 #2 :a) 保持原样,但听取taskGroup快照; 但随着值到达该集合,继续重建列表。
这些是我的建议。
这是选项 1 的一些简短代码:
// .. in your Scaffold's body:
Scaffold(
body: FutureBuilder( // the future builder fetches the initial data
future: userColeccion.doc("$userID").get(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
var groupfav = snapshot.data()!['groupfav'];
// then once the 'groupfav' has arrived,
// start listening on the taskGroup
taskGroup = FirebaseFirestore.instance
.collection("groups")
.doc(groupfav) // pass the obtained value
.collection("task")
.snapshots();
return StreamBuilder(
stream: taskGroup,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
// the rest of your code
});
}
return CircularProgressIndicator();
}
)
)
选项 2 类似于:
List<Task> userTasks = [];
void getGroupFavData() async {
var groupFavData = await userColeccion.doc("$userID").get();
var groupfav = groupFavData.data()!['groupfav'];
taskGroup = FirebaseFirestore.instance
.collection("groups")
.doc(groupfav) // pass the obtained value
.collection("task")
.snapshots().listen((snapshot) {
// here populate a list of your tasks
// and trigger a widget rebuild once you've grabbed the values
// and display it as a list on the UI
setState(() {
userTasks = snapshot.docs.map((d) => Task.fromJson(d.data())).toList();
});
});
}
在你的Scaffold中,你可以有一个ListView来呈现该任务列表中的项目,例如:
ListView.builder(
itemCount: userTasks.length,
itemBuilder: (context, index) {
// render your tasks here
})
这是一个Gist和一些工作代码来说明我的观点。 在 DartPad 上运行它,您将看到如何使用包装 StreamBuilder 的 FutureBuilder 来完成您想要的。
如果你在 DartPad 上运行上面的代码,你将得到以下 output:
希望这些指针能带你到某个地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.