How to access data stored in Future<QuerySnapshot> in FutureBuilder - flutter

This is repository where I'm accessing data using getDocumenent() which return Future<QuerySnapshot>
Future<QuerySnapshot> fetchOrderSummery() async {
var user = await FirebaseAuth.instance.currentUser();
return firestoreInstance
.collection("placeOrder")
.document(user.uid)
.collection("subPlaceOrder")
.getDocuments();
}
This is my FutureBuilder
Future<QuerySnapshot> order = state.orderSummery; //Using bloc so data return by state.orderSummery
return FutureBuilder(
future: order,
builder: (context, snapshot) {
return Column(
children: <Widget>[
Text('${order.data.documents}'),
],
);
},
);

1.Declare a variable
2. Assign during execution
3. Use the variable in the Future
Future<QuerySnapshot> _order;
_futureSearch = fetchOrderSummery()
return FutureBuilder(
future: _order,

Related

FutureBuilder widget not returnig the Pages I want - Flutter Firebase

When I try to use the FutureBuilder Widget to await a boolean value from my Firebase Database, it is not returning the values I want.
The return LoginPage() it's working fine.
Both print1 and print2 are being executed.6
Widget build(BuildContext context) {
return StreamBuilder(
stream: Auth().authStateChanges,
builder: (context, snapshot) {
if (snapshot.hasData) {
return FutureBuilder(
future: _getCurrentUserData(),
builder: ((context, AsyncSnapshot<bool> hasAccountSetup) {
if (hasAccountSetup.data == true) {
print("print1");
return MyHomePage();
} else {
print("print2");
return AccountSetup();
}
}));
} else {
return LoginPage();
}
},
);
}
Future<bool> _getCurrentUserData() async {
final DocumentSnapshot userDoc = await FirebaseFirestore.instance
.collection('Users')
.doc(Auth().currentUser!.uid)
.get();
return userDoc.get('HasSetupAccount');
}
If HasSetupAccount is a field from your firestore database then try this:
Future<bool> _getCurrentUserData() async {
final DocumentSnapshot userDoc = await FirebaseFirestore.instance
.collection('Users')
.doc(Auth().currentUser!.uid)
.get();
Map<String, dynamic> data = docSnapshot.data()!;
//HasSetupAccount should be the name of the field you want to access
return data['HasSetupAccount'];
}

How do I get all the data in a collection in flutter firestore and display it on the screen?

I wrote the following code
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
dynamic books = getData();
return Scaffold(
body: Column(
children: <Widget>[
Text(books.toString()),
],
),
);
}
}
getData() async {
QuerySnapshot querySnapshot =
await FirebaseFirestore.instance.collection('books').get();
return querySnapshot;
}
But the screen shows Instance of 'Future' How can I use the data in the firestore?
Since the data is loaded from Firestore, it won't be available immediately and in fact your getData function returns a Future<QuerySnapshot>. You'll need to use a FutureBuilder object in the UI to handle the asynchronous nature of the data.
Something like this:
FutureBuilder(
future: getData(),
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(),
}else{
return ListView(
children: snapshot.data!.docs
.map((DocumentSnapshot document) {
Map<String, dynamic> data = document.data()! as Map<String, dynamic>;
return Text(data['full_name']), // 👈 field from your document
})
.toList()
.cast(),
}
} else if (snapshot.hasError) {
return Text(snapshot.error!);
}
return CircularProgressIndicator();
}),
)
This way:
dynamic books = await getData();
Also this will open up other problems, as the build method is not async.
Use a Controller-Model-View Pattern to avoid these: The controller fetches model (data) and the view displays the model.
Or you use a StreamBuilder inside the Widget to show live data from Firebase.

how to initState and get data from where firebase

i try to create many account and create blog and every account see blog that post by itself. how to init state where in firebase. I declare variable uid in class and get it from initstate and how to use where in firebase i try to mix it with streambuilder
i declare uid in class and get data by this
void inputData() {
final User? user = auth.currentUser;
setState(() {
uid = user!.uid;
// print('uid =======> $uid');
});
}
my initstate
#override
initState() {
super.initState();
inputData(); }
final Stream<QuerySnapshot> animals = FirebaseFirestore.instance
.collection('animal')
.orderBy('createdate')
// .where('uid', isEqualTo: uid)
.snapshots();
after i use where here .I got error
The instance member 'uid' can't be accessed in an initializer.
Try replacing the reference to the instance member with a different expression
StreamBuilder<QuerySnapshot>(
stream: animals,
builder: (
BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot,
) {
if (snapshot.hasError) {
return Text('Something Went Wrong!');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text('Loading');
}
final data = snapshot.requireData;
return Container(
margin: EdgeInsets.only(top: 65),
child: ListView.builder(
shrinkWrap: true,
itemCount: data.size,
itemBuilder: (context, index) {
});
return ListTile(
title: Text(
'${data.docs[index]['animalName']}',
),
subtitle: Text(
'${data.docs[index]['animalDetail']}',
),
onLongPress: () async {
await processDeleteContent(context, data, index);
},
);
},
),
);
},
),
anyway to use where in streambuilder
Your uid is set in initState() that calls after the class is initialized. So you get uid before it is set. Try to write your animals with get so it runs code written there only when you get animals but not on initialization:
Stream<QuerySnapshot> get animals => FirebaseFirestore.instance
.collection('animal')
.orderBy('createdate')
.where('uid', isEqualTo: uid)
.snapshots();

How to pull a data from firebase and use it for pulling another data to using it in StreamBuilder

I am trying to get all postID's of the currently logged in user from the left, and I want to use this information to get all posts which includes same postID. How can I achieve this?
So far I created a function that can pull all postID's of current user and put it in a list but I think I couldn't manage to work it.
https://i.stack.imgur.com/ThfSm.png
List<String> myFavoritePosts = [];
Future<List<String>> getFavorites() async {
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = auth.currentUser;
final userID = user!.uid;
var result = await FirebaseFirestore.instance
.collection('favorites')
.where("userID", whereIn: [userID]).get();
for (var res in result.docs) {
myFavoritePosts.add((res.data()['postID'] ?? ''));
}
return myFavoritePosts;
}
But I couldn't implement it into my StreamBuilder structure.
Widget build(BuildContext context) {
final Stream<QuerySnapshot> _postStream = FirebaseFirestore.instance
.collection('Posts')
.where('postID',
isEqualTo:
getFavorites())
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: _postStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Please try again');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['title']),
subtitle: Column(
children: <Widget>[
Text(data['details']),
],
),
);
}).toList(),
);
How can I connect those two database so I can show the posts that have the same ID?
Use This:-
`
List<String> myFavoritePosts = [];
Future<List<String>> getFavorites() async {
var favourite;
final FirebaseAuth auth = FirebaseAuth.instance;
final User? user = auth.currentUser;
final userID = user!.uid;
var result = await FirebaseFirestore.instance
.collection('favorites')
.where("userID", whereIn: [userID]).get();
for (var res in result.docs) {
myFavoritePosts.add((res.data()['postID'] ?? ''));
}
myFavoritePosts.forEach((element){
favourite = element;
});
return favourite;
}`
And then:-
'Widget build(BuildContext context) {
final Stream<QuerySnapshot> _postStream = FirebaseFirestore.instance
.collection('Posts')
.where('postID',
isEqualTo:
getFavorites())
.snapshots();
return StreamBuilder<QuerySnapshot>(
stream: _postStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Please try again');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView(
children: snapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return ListTile(
title: Text(data['title']),
subtitle: Column(
children: <Widget>[
Text(data['details']),
],
),
);
}).toList(),
);'

Get SharedPreferences before widget build

I want to get my userid before the build fires in my statefulwidget.
If I do this, then build will render before I get my id. If I put it in setstate, my build will use the empty string first and then rerenders it again with my id, but this will cause unnecessary behaviours.
So how do I solve this?
String _userid = '';
Future<Null> setUserid() async {
SharedPreferences pref = await SharedPreferences.getInstance();
_userid = pref.getString('FB_USER');
}
initState() {
super.initState();
setUserid();
}
Build
// Widget build
new Flexible(
child: new StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('users')
.document(_userid)
.collection('rooms')
.snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new ListView(
children: snapshot.data.documents
.map(
(DocumentSnapshot document) => new Text('lol'),
// )
//new OverviewPresentation(presentation: document),
)
.toList(),
);
},
),
),
You can use FutureBuilder
Future<String> setUserid() async {
SharedPreferences pref = await SharedPreferences.getInstance();
_userid = pref.getString('FB_USER');
return _userid;
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: setUserid(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return ... // your widget
} else return CircularProgressIndicator();
});
Something like this
You can't, but you can guard against it being null.
Also it's easier to move the StreamBuilder to initState
String _userid = '';
dynamic _data;
Future<Null> setUserid() async {
SharedPreferences pref = await SharedPreferences.getInstance();
_userid = pref.getString('FB_USER');
_data = await Firestore.instance
.collection('users')
.document(_userid)
.collection('rooms')
.snapshots().first;
setState(() {});
}
initState() {
super.initState();
setUserid();
}
return new Flexible(
child:
if(_data == null) return new Text('Loading...');
return new ListView(
children: _data.documents
.map(
(DocumentSnapshot document) => new Text('lol'),
// )
//new OverviewPresentation(presentation: document),
)
.toList(),
);
},
),
),