Reputation: 2462
I'm using a FutureBuilder
in my code in order to query Firestore
but I keep getting no data from the function I specified in the FutureBuilder
. But funny enough the function is executing and getting the data. It is just not passing it to the FutureBuilder
.
Code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:garuda_academy_app/Tools/FixedColors.dart';
class CoursePage extends StatefulWidget {
CoursePage({this.userEmail});
final String userEmail;
@override
_CoursePageState createState() => _CoursePageState();
}
class _CoursePageState extends State<CoursePage> {
@override
void initState() {
super.initState();
}
Future<List<DocumentSnapshot>> _getCourses() async {
List<DocumentSnapshot> userCourses = [];
await Firestore.instance
.collection("Users")
.document(widget.userEmail)
.get()
.then((DocumentSnapshot userDetails) {
List<dynamic> courses = userDetails["Courses"];
courses.forEach((dynamic course) {
Firestore.instance
.collection("Courses")
.document(course)
.get()
.then((DocumentSnapshot courseDetails) {
userCourses.add(courseDetails);
print(userCourses.length);
});
});
});
return userCourses;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: secondaryColor,
resizeToAvoidBottomInset: false,
body: FutureBuilder(
future: _getCourses(),
builder: (context, AsyncSnapshot<List<DocumentSnapshot>> snapshot) {
// loading display
if (snapshot.hasError ||
(snapshot.connectionState == ConnectionState.waiting)) {
if (snapshot.hasError) print('${snapshot.error}');
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(primaryColor),
),
);
}
print(snapshot.data.length);
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Text(
snapshot.data[index].documentID,
style: TextStyle(color: Colors.black),
);
},
);
},
),
);
}
}
Notice I print the data length twice to check if I am getting anything, the output is as such:
0 // the future print
1 // the function print
It seems like await
is not functioning as it should as the future seems to take the List
before await
.
Does anyone know why this is happening ?
Upvotes: 0
Views: 6861
Reputation: 622
The Firestore instances needs to be call from a StreamBuilder not FutureBuilder you can se this page from Flutter docs about this widget.
this is the example the team have:
StreamBuilder<int>(
stream: _lot?.bids, // a Stream<int> or null
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.none: return Text('Select lot');
case ConnectionState.waiting: return Text('Awaiting bids...');
case ConnectionState.active: return Text('\$${snapshot.data}');
case ConnectionState.done: return Text('\$${snapshot.data} (closed)');
}
return null; // unreachable
},
)
Upvotes: 0
Reputation: 4094
Problem is you are calling async method in inside FutureBuilder Widget. call that function inside initState method and get that return value in one varible and use that in FutureBuilder Widget.
Check this link for more understanding
Future<List<DocumentSnapshot>> _course;
void initState()
{
super.initState();
course= _getCourses()
}
use course variable in FutureBuilder Widget
FutureBuilder(
future: _course,
builder: write your code)
Upvotes: 2