英文:
How can I get StreamBuilder results after a Firestore query has been completed?
问题
I have a query for retrieving data from a Firestore collection, and values from that query are used to define the stream to be built by StreamBuilder.
我有一个用于从Firestore集合检索数据的查询,该查询的值用于定义由StreamBuilder构建的流。
What I have found is that StreamBuilder builds the stream before the Firestore query has been completed, which produces a different result than if the query had completed and then StreamBuilder had built.
我发现StreamBuilder在Firestore查询完成之前构建流,这会产生与如果查询完成然后StreamBuilder构建的结果不同的结果。
Is there a way for Flutter to be written so that a Future type of query can be completed before the UI is built with StreamBuilder?
是否有一种方法可以编写Flutter代码,以便在使用StreamBuilder构建UI之前完成Future类型的查询?
英文:
I have a query for retrieving data from a Firestore collection, and values from that query are used to define the stream to be built by StreamBuilder.
What I have found is that StreamBuilder builds the stream before the Firestore query has been completed, which produces a different result than if the query had completed and then StreamBuilder had built.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
@override
Widget build(BuildContext context) {
getData();
final _dataSource = FirebaseFirestore.instance
.collection(
'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
return StreamBuilder<QuerySnapshot>(
stream: _dataSource.where('preferredCurrency', isEqualTo: currency).snapshots().distinct(), // exclusiveA is being read
// results should return only documents where preferredCurrency field = the value of currency field
builder: (context, snapshot) {
<!-- end snippet -->
Is there a way for Flutter to be written so that a Future type of query can be completed before the UI is built with StreamBuilder?
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
flutter: Login successful.
flutter: The vehicle's maximum speed = 233.0.
flutter: The vehicle's pulling strength = 2222.0 bhp.
flutter: The vehicle's brand is CCCCC, and its model-name is BBBBB.
flutter: The preferred currency = GBP.
flutter: The vehicle's maximum speed = 220.0.
flutter: The vehicle's pulling strength = 9000.0 bhp.
flutter: The vehicle's brand is PPPPP, and its model-name is LLLLL.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 440.0 bhp.
flutter: The vehicle's brand is KEXUZ, and its model-name is N2000.
flutter: The preferred currency = YEN.
flutter: The vehicle's maximum speed = 88.0.
flutter: The vehicle's pulling strength = 1100.0 bhp.
flutter: The vehicle's brand is Eord, and its model-name is Eiesta.
flutter: The preferred currency = GBP.
flutter: The vehicle's maximum speed = 110.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is Zadilax, and its model-name is Zrechlax.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 300.0.
flutter: The vehicle's pulling strength = 3200.0 bhp.
flutter: The vehicle's brand is XXXXX, and its model-name is XXXXXXXXXX.
flutter: The preferred currency = YEN.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is MMMMM, and its model-name is MATHEMS.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 110.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is Zadilax, and its model-name is Azerlax.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is AAAAAAAAA, and its model-name is BBBBBBBBB.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 280.0.
flutter: The vehicle's pulling strength = 2234.0 bhp.
flutter: The vehicle's brand is ABCDE12345, and its model-name is TEST MAY 24.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = null.
flutter: The vehicle's pulling strength = null bhp.
flutter: The vehicle's brand is , and its model-name is .
flutter: The preferred currency = .
flutter: The vehicle's maximum speed = 120.0.
flutter: The vehicle's pulling strength = 320.0 bhp.
flutter: The vehicle's brand is Snow Patrol, and its model-name is HD Rider 100.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is AAAAAAAA, and its model-name is BBBBBBBB.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 220.0.
flutter: The vehicle's pulling strength = 3200.0 bhp.
flutter: The vehicle's brand is Neverlet, and its model-name is NL 5000.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 1234.0.
flutter: The vehicle's pulling strength = 1111.0 bhp.
flutter: The vehicle's brand is XXXXXZZZZZ, and its model-name is SASSCF.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 123456789.0.
flutter: The vehicle's pulling strength = 123456.0 bhp.
flutter: The vehicle's brand is MAY 22, and its model-name is Y2023.
flutter: The preferred currency = YEN.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is XXXXX, and its model-name is ZZZZZ.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 250.
flutter: The vehicle's pulling strength = 500 bhp.
flutter: The vehicle's brand is CMW, and its model-name is K325S.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 80.0.
flutter: The vehicle's pulling strength = 1200.0 bhp.
flutter: The vehicle's brand is Niatt, and its model-name is POQ 123.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 225.0.
flutter: The vehicle's pulling strength = 12345.0 bhp.
flutter: The vehicle's brand is TTTTT, and its model-name is YYYYY.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = null.
flutter: The vehicle's pulling strength = null bhp.
flutter: The vehicle's brand is Percedes B, and its model-name is XLK.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 100.0.
flutter: The vehicle's pulling strength = 1000.0 bhp.
flutter: The vehicle's brand is WWWWW, and its model-name is WATCHEMS.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 200.
flutter: The vehicle's pulling strength = 500 bhp.
flutter: The vehicle's brand is Vercedes, and its model-name is QWE223.
flutter: The preferred currency = GBP.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 900.0 bhp.
flutter: The vehicle's brand is Percedes ZZ, and its model-name is ASLK.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2222.0.
flutter: The vehicle's pulling strength = 1234.0 bhp.
flutter: The vehicle's brand is Vvvvvvvv, and its model-name is Aaaaaaaaa.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 500.0.
flutter: The vehicle's pulling strength = 500.5 bhp.
flutter: The vehicle's brand is J5 Ingram, and its model-name is B Way.
flutter: The preferred currency = USD.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 550.0 bhp.
flutter: The vehicle's brand is Vercedes ZXC, and its model-name is X46i.
flutter: The preferred currency = Euros.
flutter: The vehicle's maximum speed = 876543.0.
flutter: The vehicle's pulling strength = 1234.0 bhp.
flutter: The vehicle's brand is Ssssssss, and its model-name is Zzzzzzz.
flutter: The preferred currency = ZZZ.
flutter: The vehicle's maximum speed = 250.5.
flutter: The vehicle's pulling strength = 770.7 bhp.
flutter: The vehicle's brand is Vercedes ZXC, and its model-name is L55i.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2800.0.
flutter: The vehicle's pulling strength = 1100.0 bhp.
flutter: The vehicle's brand is ZZZZZ, and its model-name is ZAPPEMS.
flutter: The preferred currency = EUR.
flutter: The current user's ID is: gaWoPCiLPWef9mCmd6WngDiS1I63 and their currency-choice = YEN.
<!-- end snippet -->
The details above show the result where the Future type query isn't completed before the StreamBuilder begins to build: a print statement to Flutter's console from the Future query is the very last output from Flutter, whereas the stream is the entire collection's data.
What's meant to happen is, the Future query should complete first and confirm the 'currency' value, then the StreamBuilder results should be filtered to show only the results where the currency matches the 'currency' value from the query.
答案1
得分: 0
在Flutter中,您可以使用FutureBuilder
小部件等待Future任务完成其执行。
以下是您的更新后的代码:
@override
Widget build(BuildContext context) {
return FutureBuilder<QuerySnapshot>(
future: getFutureData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// 在执行查询时显示加载指示器
return CircularProgressIndicator();
}
if (snapshot.hasError) {
// 处理查询期间发生的任何错误
return Text('错误:${snapshot.error}');
}
final _dataSource = snapshot.data.docs; // 访问查询结果中的文档
return StreamBuilder<QuerySnapshot>(
stream: _dataSource
.where('preferredCurrency', isEqualTo: currency)
.snapshots()
.distinct(),
builder: (context, snapshot) {
// 基于流的快照构建您的UI
// ...
},
);
},
);
}
Future<QuerySnapshot> getFutureData() {
final collectionRef = FirebaseFirestore.instance.collection(
'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
return collectionRef.get();
}
希望这有所帮助!如果您需要进一步的帮助,请告诉我。
英文:
Yes, in flutter you can wait till Future task compete its execution with FutureBuilder
widget.
Here is your updated code
@override
Widget build(BuildContext context) {
return FutureBuilder<QuerySnapshot>(
future: getFutureData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// Show a loading indicator while the query is being executed
return CircularProgressIndicator();
}
if (snapshot.hasError) {
// Handle any error that occurred during the query
return Text('Error: ${snapshot.error}');
}
final _dataSource = snapshot.data.docs; // Access the documents from the query result
return StreamBuilder<QuerySnapshot>(
stream: _dataSource
.where('preferredCurrency', isEqualTo: currency)
.snapshots()
.distinct(),
builder: (context, snapshot) {
// Build your UI based on the snapshot of the stream
// ...
},
);
},
);
}
Future<QuerySnapshot> getFutureData() {
final collectionRef = FirebaseFirestore.instance.collection(
'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
return collectionRef.get();
}
答案2
得分: 0
以下是您要翻译的内容:
"After posting this question I thought of a way to resolve the problem that I had.
I thought that if I could call the query from another class such as the class from which a recent navigation had occurred, then the data that StreamBuilder will not wait for a Future to deliver, could be made available in time for the Stream Builder. I tried this way and it worked perfectly.
Another thing I found working on this solution, was that I didn't need the Firestore query at all, and this is because the data originated from the class that navigated towards the StreamBuilder's class. So, all I had to do was transfer some existing data.
The technique I chose was to create a constructor for the class where the StreamBuilder was present, and then at the Navigator call, add the relevant data when calling that class. Doing this ensured that when the StreamBuilder began to build, the 'currency' value was available so that the StreamBuilder results could be filtered in accordance with the chosen currency."
"The details above show the result of having the data required by the StreamBuilder transferred from another class."
In the details above you can see the constructor for the StreamResults class which is a part of the solution.
The details above show the solution's Navigator call for changing screens and for transferring data at the same time.
英文:
After posting this question I thought of a way to resolve the problem that I had.
I thought that if I could call the query from another class such as the class from which a recent navigation had occurred, then the data that StreamBuilder will not wait for a Future to deliver, could be made available in time for the Stream Builder. I tried this way and it worked perfectly.
Another thing I found working on this solution, was that I didn't need the Firestore query at all, and this is because the data originated from the class that navigated towards the StreamBuilder's class. So, all I had to do was transfer some existing data.
The technique I chose was to create a constructor for the class where the StreamBuilder was present, and then at the Navigator call, add the relevant data when calling that class. Doing this ensured that when the StreamBuilder began to build, the 'currency' value was available so that the StreamBuilder results could be filtered in accordance with the chosen currency.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
flutter: Login successful.
flutter: The vehicle's maximum speed = 220.0.
flutter: The vehicle's pulling strength = 9000.0 bhp.
flutter: The vehicle's brand is PPPPP, and its model-name is LLLLL.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is AAAAAAAA, and its model-name is BBBBBBBB.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2000.0.
flutter: The vehicle's pulling strength = 2000.0 bhp.
flutter: The vehicle's brand is XXXXX, and its model-name is ZZZZZ.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 80.0.
flutter: The vehicle's pulling strength = 1200.0 bhp.
flutter: The vehicle's brand is Niatt, and its model-name is POQ 123.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 225.0.
flutter: The vehicle's pulling strength = 12345.0 bhp.
flutter: The vehicle's brand is TTTTT, and its model-name is YYYYY.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = null.
flutter: The vehicle's pulling strength = null bhp.
flutter: The vehicle's brand is Percedes B, and its model-name is XLK.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 100.0.
flutter: The vehicle's pulling strength = 1000.0 bhp.
flutter: The vehicle's brand is WWWWW, and its model-name is WATCHEMS.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 235.0.
flutter: The vehicle's pulling strength = 900.0 bhp.
flutter: The vehicle's brand is Percedes ZZ, and its model-name is ASLK.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 230.0.
flutter: The vehicle's pulling strength = 2300.0 bhp.
flutter: The vehicle's brand is EEEEE, and its model-name is EEEEEEEEEE.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2222.0.
flutter: The vehicle's pulling strength = 1234.0 bhp.
flutter: The vehicle's brand is Vvvvvvvv, and its model-name is Aaaaaaaaa.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 250.5.
flutter: The vehicle's pulling strength = 770.7 bhp.
flutter: The vehicle's brand is Vercedes ZXC, and its model-name is L55i.
flutter: The preferred currency = EUR.
flutter: The vehicle's maximum speed = 2800.0.
flutter: The vehicle's pulling strength = 1100.0 bhp.
flutter: The vehicle's brand is ZZZZZ, and its model-name is ZAPPEMS.
flutter: The preferred currency = EUR.
<!-- end snippet -->
The details above show the result of having the data required by the StreamBuilder transferred from another class.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
class StreamResults extends StatelessWidget {
final _auth = auth.FirebaseAuth.instance;
final _dB = FirebaseFirestore.instance;
final _dataSource = FirebaseFirestore.instance
.collection(
'users/l9NzQFjN4iB0JlJaY3AI/userA/2VzSHur3RllcF5PojT61/exclusiveA');
String? vehicleMake, vehicleTitle, currentUserID, pCurrency, currency, uid, docRefID;
num? maxSpeed, pullStrength;
StreamResults({this.uid, this.currency, this.docRefID});
<!-- end snippet -->
In the details above you can see the constructor for the StreamResults class which is a part of the solution.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-css -->
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder:(context) => StreamResults(uid: uid, currency: currency, docRefID: docRefID)), (route) => false);
<!-- end snippet -->
The details above show the solution's Navigator call for changing screens and for transferring data at the same time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论