How to get data in stream builder with the multiple conditions/queries? - flutter

I am trying to display post with queries in Page view builder with the help of stream builder but not able to get the data with the separate function I made. I have tried calling the function in stream but then I don't get any data. how can I call the following function in stream. Or do I need to try something else instead of stream builder?
If I do this then it display the Page view builder but with no condition and fetch all the data.
StreamBuilder<QuerySnapshot>(
stream:FirebaseFirestore.instance.collection('users')..doc(auth.currentUser.uid)
.collection('plans').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot){
if (!snapshot.hasData){
return Text(
"No Data",
);
}if(snapshot.hasData){
return PageView.builder(.........),
And if I call getUserPlan() then I dont get data.
StreamBuilder<QuerySnapshot>(
stream: getUserPlan(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot){
if (!snapshot.hasData){
return Text(
"No Data",
);
}if(snapshot.hasData){
return PageView.builder(.........),
function getUserPlan:- // I want to stream data with all this queries/conditions.
getUserPlan() {
List pUser = [];
FirebaseFirestore.instance.collection('users').doc(auth.currentUser.uid)
.collection('plans').where('pTimeStamp',
isGreaterThanOrEqualTo: DateTime.now())
.orderBy('pTimeStamp', descending: true).get().then((_){
query().get().then((data)async{
if (data.docs.length < 1 ) {
print("no more Plan data");
return;
}
for (var doc in data.docs) {
CreateAccountData temp = CreateAccountData.fromDocument(doc);
var distance = calculateDistance(
currentUser.coordinates['latitude'],
currentUser.coordinates['longitude'],
temp.coordinates['latitude'],
temp.coordinates['longitude']);
temp.distanceBW = distance.round();
if (pUser.any(
(value) => value == temp.uid,
)) {
} else {
if (distance <= currentUser.maxDistance && temp.uid != currentUser.uid && !temp.isBlocked){pUsers.add(temp);}
}
}
if (mounted) setState(() {});
});
});
}
query() {
if (currentUser.showGender == 'everyone') {
return docRef
.where('age',
isGreaterThanOrEqualTo: currentUser.ageRange['min'],
)
.where('age',
isLessThanOrEqualTo:currentUser.ageRange['max'])
.orderBy('age', descending: false).limit(30);
} else {
return docRef
.where('editInfo.userGender', isEqualTo: currentUser.showGender)
.where('age',
isGreaterThanOrEqualTo:currentUser.ageRange['min'],
)
.where('age',
isLessThanOrEqualTo: currentUser.ageRange['max'])
.orderBy('age', descending: false).limit(30);
}
}

Related

Future Builder with for loop in flutter

In my application, I have two future builders:
CollectionReference stream = Firestore.instance.collection('users');
List<String> myIDs =[];
List <dynamic> mylist =[];
List<String> myNames =[];
String? userName;
Widget userValues() {
return FutureBuilder(
future: getrecords(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Text(snapshot.data? [index] ?? "got null");
},
);
}
else {
return CircularProgressIndicator();
}
},
);
}
..................
Future getrecords() async{
final data = await stream.get();
mylist.addAll(data);
mylist.forEach((element) {
final String firstPartString = element.toString().split('{').first;
final String id = firstPartString.split('/').last;
myIDs.add(id.trim());
});
return(myIDs);
}
....................
Widget Names() {
return FutureBuilder(
future: getNames(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Text(snapshot.data?[index] ?? "got null");
},
);
}
else {
return CircularProgressIndicator();
}
},
);
}
............................
Future getNames() async{
for (var id in myIDs ){
var names = stream.document(id).collection('userName').document('userName');
var document = await names.get();
userName = document['name'];
myNames.add(userName!);
}
return(myNames);
}
The first future (userValues) works fine, and I get the result just fine, but the other one with the for loop is not working properly and is not returning values until I hot reload, then a name will be added to the list, and so on with each hot reload.
What I want to achieve is to keep the loading indicator until the for loop is over, then build the screen.
UPDATE:
If I could manage to make it so that the "Names" futurebuilder awaits for the userValues to complete before starting, then my problem would be solved, but what I realized is that it's taking the initial value of the return from "userValues," which is non, and using it to build.
Future getNames() async{
await Future.delayed(const Duration(seconds: 2));
for (var id in myIDs ){
var names = stream.document(id).collection('userName').document('userName');
var document = await names.get();
userName = document['name'];
myNames.add(userName!);
}
return(myNames);
}
When I added this 2 seconds delay, it worked properly but is there any other way to make it wait for the first future to complete then start the second one?
You can use the await keyword on the future returned from getrecords() to wait for the completion of getrecords() before starting the getNames() function:
Future getNames() async{
await getrecords();
for (var id in myIDs ){
var names = stream.document(id).collection('userName').document('userName');
var document = await names.get();
userName = document['name'];
myNames.add(userName!);
}
return(myNames);
}

How to get values inside _JsonDocumentSnapshot?

Flutter Streambuilder code below runs without error and returns (screenshot at bottom):
ID: AzFdOO9WsFaFbTxTQsuo
Data: Instance of '_JsonDocumentSnapshot'
How do I get to the values inside the _JsonDocumentSnapshot and display them in the Text() widget?
For instance, there's a string field called "name", but I can't figure out how to get to it.
StreamBuilder(
stream: FirebaseFirestore.instance
.collection("groceries")
.doc(widget.docId)
.snapshots(),
builder: (context, streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
} else if (streamSnapshot.hasData) {
return Text("ID: ${widget.docId}\n"
"Data: ${streamSnapshot.data}");
} else {
return const Text("No Data");
}
}
)
Thanks for your help!
the following Stream, return an object with a type of DocumentSnapshot :
FirebaseFirestore.instance.collection("groceries").doc(widget.docId).snapshots();
and that type contains the document snapshot, and also contains more additional information about the document.
so in order to get the JSON Map<String, dynamic> which represents the data of the Firestore document, you need to call data() on the result of the snapshot.data(), so you need to try the following:
StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection("groceries")
.doc(widget.docId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> streamSnapshot) {
if (streamSnapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
} else if (streamSnapshot.hasData) {
return Text("ID: ${widget.docId}\n"
"Data: ${streamSnapshot.data.data()}"); // added data()
} else {
return const Text("No Data");
}
}
)
now it should show the Map<String, dynamic> object which contains your document data in the Text widget.
hope this helps.
In your code example streamSnapshot.data is an Object or a dynamic type variable.
To access the json value of your data, you have to specify the key corresponding to your value.
streamSnapshot.data['banana']

How to check for an empty array in FirebaseFirestore using StreamBuilder flutter

I have a StreamBuilder to check for an empty string But I want to turn it to check for an empty array. How can I do that?
bool? checkEmpty = false;
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance
.collection('widgets')
.doc(widgets)
.snapshots(),
builder: (context, snapshot) {
snapshot.data?.data()?.forEach((key, value) {
if (key == 'imageUrl') {
checkEmpty = value == [];
}
});
return ...
checkEmpty!
? Text('Array is not empty')
: Text('Empty array'),
cast the value type as List then check over it.
try the following:
bool? checkEmpty = false;
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance
.collection('widgets')
.doc(widgets)
.snapshots(),
builder: (context, snapshot) {
snapshot.data?.data()?.forEach((key, value) {
if (key == 'imageUrl') {
checkEmpty = (value as List).isEmpty;
}
});
return ...
checkEmpty!
? Text('Array is not empty')
: Text('Empty array'),

How to get snapshot from groupScreen? flutter firebase

I have created a group screen in my flutter app and when I hit the create button it create a group as described is code:
//Create group
Future<String> createGroup(String groupName1, userUid) async {
String retVal = "error";
List<String> members = [];
try {
members.add(userUid);
DocumentReference docRef;
docRef = await firestore.collection("groups").add({
'name': groupName1,
'leader': userUid,
'members': members,
'groupCreate': Timestamp.now(),
});
retVal = "success";
} catch (e) {
// ignore: avoid_print
print(e);
}
return retVal;
}
I am stuck in getting the snapshot from my FBbackend. I want to get the info and display is on my group screen. How can I achieve that?
I have try to get the snapshot but it says Text("..."). I think the problem is that the value of DocumentReference? docRef; is empty, but I don’t know how to fixed it.
code:
DocumentReference? docRef;
docRef == null
? const Text('Error No Group Name Found!!')
: // 👈 handle null here
StreamBuilder<DocumentSnapshot<Map<String, dynamic>>>(
stream: FirebaseFirestore.instance
.collection('groups')
.doc(docRef!.id)
.snapshots(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return const ErrorScreen();
}
return Center(
child: Text((snapshot.data
as DocumentSnapshot<
Map<String, dynamic>>)['name']),
);
}),

Move method to streambuilder

List<Photo> imgList = [];
Future getCarouselWidget() async {
var firestore = Firestore.instance;
QuerySnapshot qn =
await firestore.collection("history").getDocuments();
List pics = qn.documents
.map((it) => Photo(it['photo'].toString(), it['name'].toString(), it['address'].toString()))
.toList();
return imgList = pics;
}
Hi all, when I make changes in my DB I dont see them in my app? can anybody help me or guid me how to wire this to stream builder or query the stream
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('swimfinderlakes')
.snapshots(),
builder: (context, snapshot) {
Every time Firestore has a change, it'll trigger the StreamBuilder. U can then access the most recently update with the snapshot on the builder method. Then you can use it to update the ui accordingly.
StreamBuilder<QuerySnapshot>(
stream: Firestore.instance
.collection('swimfinderlakes')
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
if (snapshot.hasData) {
List pics = qn.documents
.map((it) => Photo(it['photo'].toString(),
it['name'].toString(), it['address'].toString())).toList();
return pics;
}
} else {
return CircularProgressIndicator();
}
}