英文:
Flutter Streambuilder stuck in connectionstate.waiting
问题
我有一个关于Flutter应用程序的问题。我想通过Firebase Firestore按Document id接收数据。问题是,我无法在一个集合中复制数据,所以我必须使用两个集合。
我的数据是一个Measurement(String,String,...,List
MeasurementData(String,String,Number)
据我了解Firestore,我不能在一个集合中制作这样的列表,所以我创建了第二个集合,其中每个文档由三个数组组成。我还保存了Measurement文档的id。为了在Flutter中使用它,我使用了StreamBuilder小部件。为了更容易访问,我在使用文档之前将其转换为Dart对象。因为我有两个要转换为一个对象的流,我有一个先行流StreamMeasurement对象,它基本上与Measurement对象相同,但没有MeasurementData列表,因为这需要首先创建,而只保存了MeasurementData文档的id。之后,我使用Rx.zip2从StreamMeasurement对象创建一个Measurement对象,并添加List
Class Service
/// Firebase实例
FirebaseFirestore db = FirebaseFirestore.instance;
/// 通过其id查找并返回[Measurement]
Stream<Measurement> getById(String id) {
Stream<StreamMeasurement> streamMeasurementStream = db.collection("measurements").doc(id)
.snapshots().map((document) => StreamMeasurement.fromJson(document.data()!));
return Rx.zip2(streamMeasurementStream, getMeasurementDataStreamById(id),
(StreamMeasurement streamMeasurement, List<MeasurementData> measurementData) {
Measurement measurement = Measurement.fromStreamMeasurement(streamMeasurement, measurementData);
if (measurement == null) {
// TODO 写一个具体的异常来抛出和捕捉
throw Exception('Measurement Stream is null');
}
return measurement;
});
}
/// 为给定的Measurement id返回[Stream<List<MeasurementData>>]
Stream<List<MeasurementData>> getMeasurementDataStreamById(String id) {
return db.collection("measurementData").where("measurement", isEqualTo: id)
.snapshots()
.map((querySnapshot) => querySnapshot.docChanges)
.expand((changes) => changes)
.map((change) => change.doc).map((document) => MeasurementData.fromJson(document.data()!));
}
Class DetailScreen
@override
Widget build(BuildContext context) {
MeasurementService measurementService = MeasurementService();
Stream<Measurement> measurementstream = measurementService.getById(
"GmfzveKeozkcfdlrk75s");
return StreamBuilder<Measurement>(
stream: measurementstream,
builder: (BuildContext context, AsyncSnapshot<Measurement> snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
return Text('出错了' + snapshot.error.toString());
}
if (snapshot.connectionState == ConnectionState.waiting) {
print(snapshot);
return Text("加载中" + snapshot.connectionState.toString());
}
Measurement? measurement = snapshot.data;
return SafeArea(/*你的Widget代码*/);
});
}
打印(snapshot) => I/flutter (19335): AsyncSnapshot
结果是,如果我使用getById(id)函数,StreamBuilder会停留在ConnectionState.waiting状态。
英文:
i have a problem with a Flutter application.
I want to receive data from a firebase firestore by an Document id.
The problem is, i cant replicate the data in one collection, so i have to use two collections.
My data ist a Measurement(String, String,..., List<MeasurementData>)
MeasurementData(String,String,Number)
As far as i understand the Firestore i cant make such a list in one collection, so i have created a second one in whitch each document consists of three arrays. I also save the id from the Measurement Document where it belongs to.
To use it in Flutter a use a StreamBuilder widget. For easer access i convert the document bevor using into a Dart Object. Because i have two Streams which should be converted to one Object i have a predessecor StreamMeasurement object which is basicly the same as the Measurement Object, but without the MeasurementData list, because this first needs to be created, instead it only saves a id for the measurementData Document.
After that i use the Rx.zip2 to create an Measurement Object from the StreamMeasurement Object and add the List<MeasurementData> to have a complete object.
Class Service
/// The firebase instance
FirebaseFirestore db = FirebaseFirestore.instance;
///Finds and returns a [Measurement] by its [id]
Stream<Measurement> getById(String id) {
Stream<StreamMeasurement> streamMeasurementStream =db.collection("measurements").doc(id)
.snapshots().map((document) => StreamMeasurement.fromJson(document.data()!));
return Rx.zip2(streamMeasurementStream, getMeasurementDataStreamById(id)
, (StreamMeasurement streamMeasurement, List<MeasurementData> measurementData) {
Measurement measurement = Measurement.fromStreamMeasurement(streamMeasurement, measurementData);
if(measurement == null)
{
//TODO Write a concrete exception to throw and catch
throw Exception('Measurement Stream is null');
}
return measurement;
}) ;
}
/// Returns a [Stream<List<MeasurementData>>] for a given Measurement id
Stream<List<MeasurementData>> getMeasurementDataStreamById(String id)
{
return db.collection("measurementData").where("measurement", isEqualTo: id).
snapshots().
map((querySnapshot) => querySnapshot.docChanges)
.expand((changes) => changes)
.map((change) => change.doc).map((document) => MeasurementData.fromJson(document.data()!));
}
Class DetailScreen
@override
Widget build(BuildContext context) {
MeasurementService measurementService = MeasurementService();
Stream<Measurement> measurementstream = measurementService.getById(
"GmfzveKeozkcfdlrk75s");
return StreamBuilder<Measurement>(
stream: measurementstream,
builder: (BuildContext context, AsyncSnapshot<Measurement> snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
return Text('Something went wrong' + snapshot.error.toString());
}
if (snapshot.connectionState == ConnectionState.waiting) {
print(snapshot);
return Text("Loading" + snapshot.connectionState.toString());
}
Measurement? measurement = snapshot.data;
return SafeArea(
Print(snapshot) => I/flutter (19335): AsyncSnapshot<Measurement>(ConnectionState.waiting, null, null, null)
The result is, that the StreamBuilder is stuck in ConnectionState.waiting state if i use the getById(id) function
答案1
得分: -1
问题已解决。问题出在ID前有一个不匹配的空格。
编辑:我在数据库中手动硬编码了ID,写的时候在ID前留下了一个空格,这个空格不应该存在,所以请求无法正常工作,应该是"1234"而不是" 1234"。
英文:
Okay, ... Question solved. The problem was a unmatched whitespace before the id
EDIT: I had hardcodet the ID manually in the database, while writing i had left an whitespace before id, that doesnt belongs there and so the request doesnt work like " 1234" should be "1234"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论