How to access data from firestore using streambuilder flutter - firebase

I want to access data from firestore but there are errors, how can i do that?
I cant use .docs in snapshot.
StreamBuilder(
stream: messageStream,
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
padding: EdgeInsets.only(bottom: 70, top: 16),
reverse: true,
itemCount: snapshot.data.docs.length, // error
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot ds =
snapshot.data!.docs[index]; // error
return _buildMessage(
ds["message"], myUserName == ds["sendBy"]);
},
)
: Center(
child: CircularProgressIndicator(),
);
},
),
Stream:
getChatRoomMessages(chatRoomId) async {
return FirebaseFirestore.instance.collection("chatRooms").doc(chatRoomId).collection("chats").orderBy("ts", descending: true).snapshots();}

in the StreamBuilder you have to use AsyncSnapshot in with your snapshot property. That was what got it working for me
StreamBuilder<QuerySnapshot>(
stream: DatabaseMethods().getChatRoomMessages(chatRoomId),
builder: (context, AsyncSnapshot snapshot) { <<<< insert here
return snapshot.hasData
? ListView.builder(
padding: EdgeInsets.only(bottom: 70, top: 16),
reverse: true,
itemCount: snapshot.data!.docs.length, // error
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot ds =
snapshot.data!.docs[index]; // error
return _buildMessage(
ds["message"], myUserName == ds["sendBy"]);
},
)
: Center(
child: CircularProgressIndicator(),
);
},
),

I found a solution:
StreamBuilder<QuerySnapshot>(
stream: DatabaseMethods().getChatRoomMessages(chatRoomId),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
padding: EdgeInsets.only(bottom: 70, top: 16),
reverse: true,
itemCount: snapshot.data!.docs.length, // error
itemBuilder: (BuildContext context, int index) {
DocumentSnapshot ds =
snapshot.data!.docs[index]; // error
return _buildMessage(
ds["message"], myUserName == ds["sendBy"]);
},
)
: Center(
child: CircularProgressIndicator(),
);
},
),

Related

How can use firestore using where and orderby in flutter?

How can use firestore using where and orderby in flutter?
When I wanna to use both, I got the error.
Exception has occurred.
_CastError (Null check operator used on a null value)
code
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Posts')
.where('country', isEqualTo: user.country)
//.where('country', isEqualTo: 'Australia')
.orderBy('time', descending: true)
.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
//print(user.country);
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) => Container(
margin: EdgeInsets.symmetric(
horizontal: width > webScreenSize ? width * 0.3 : 0,
vertical: width > webScreenSize ? 15 : 0),
child: PostCard(
snap: snapshot.data!.docs[index],
),
),
);
},
So, why I could not got the data? I'd got the user.value.
The problem is that you're telling Flutter that snapshot.data is guaranteed to have a value, when in reality it doesn't here:
return ListView.builder(
itemCount: snapshot.data!.docs.length,
I recommend reading the documentation for StreamBuilder again, as there are many more states than snapshot.connectionState == ConnectionState.waiting that you need to handle.
For example, there could be an error, or there could be no data for another reason:
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Posts')
.where('country', isEqualTo: user.country)
.orderBy('time', descending: true)
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
}
// 👇 Handle error
if (snapshot.hasError) {
return const Center(
child: Text(snapshot.error),
);
}
// 👇 Handle lack of data
if (!snapshot.hasData) {
return const Center(
child: Text("Something when wrong - no data available"),
);
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) => Container(
margin: EdgeInsets.symmetric(
horizontal: width > webScreenSize ? width * 0.3 : 0,
vertical: width > webScreenSize ? 15 : 0),
child: PostCard(
snap: snapshot.data!.docs[index],
),
),
);

I can't get data stream from firestore how do I fix this ØŸ

I tried fetching the data without using the StreamBuilder and all the data was fetched successfully but when I used the StreamBuilder it didn't work
StreamBuilder(
stream: Firestore.instance.collection('chats/IClRN96vdYSpdtfT4PZh/messeges').snapshots(),
builder: (ctx , snap) {
if(snap.connectionState == ConnectionState.waiting){
return Center(child: CircularProgressIndicator(),);
}
return ListView.builder(
itemCount: snap.data.documents.length,
itemBuilder: (ctx, i) => Container(
padding: EdgeInsets.all(10),
child: Text('Text Chat messeges'),
));
})
replace snap.data.documents.length with snap.data.docs.length
add AsyncSnapshot<QuerySnapshot> to snap
StreamBuilder(
stream: Firestore.instance.collection('chats/IClRN96vdYSpdtfT4PZh/messeges').snapshots(),
builder: (ctx , AsyncSnapshot<QuerySnapshot> snap) {
if(snap.connectionState == ConnectionState.waiting){
return Center(child: CircularProgressIndicator(),);
}
return ListView.builder(
itemCount: snap.data!.documents.length,
itemBuilder: (ctx, i) => Container(
padding: EdgeInsets.all(10),
child: Text('Text Chat messeges'),
));
})
**And before the documents put ! **

i got this error when i am trying to use snapshot.data.docs.length in listview.buider: The getter 'docs' isn't defined for the type 'Object'

I am trying to fetch data from firebase to list all the documents in a listview builder the code is still not completed in term of displaying the database filed in the code. this is the error: The getter 'docs' isn't defined for the type 'Object'
Container(
child: StreamBuilder<Object>(
stream: _firestore
.collection('Patient')
.doc(_auth.currentUser.email)
.collection("Diabetes")
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
reverse: true,
shrinkWrap: true,
itemCount:
snapshot.data.docs.length, // here is the error "docs"
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot =
snapshot.data.docs[index]; // also another error "docs"
return Container();
});
}
return Center(
child: CircularProgressIndicator(),
);
}),
)
You should replace snapshot.data.docs.length with snapshot.data.length
Container(
child: StreamBuilder<Object>(
stream: _firestore
.collection('Patient')
.doc(_auth.currentUser.email)
.collection("Diabetes")
.snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
reverse: true,
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot = snapshot.data[index];
return Container();
});
}
return Center(
child: CircularProgressIndicator(),
);
}),
)
I solved the problem by replacing StreamBuilder<Object> with StreamBuilder<QuerySnapshot>. by default the StreamBuilder comes in this form StreamBuilder<Object>

The property 'docs' cannot be unconditionally accessed because received can be 'null' Flutter

After migrate to null-safety showing this error. What should I do now?
Widget chatMessages() {
return StreamBuilder(
stream: messageStream,
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
padding: EdgeInsets.only(bottom: 70, top: 16),
itemCount: snapshot.data.docs.length,
reverse: true,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.docs[index];
return chatMessageTitle(
ds["message"], myUserName == ds["sendBy"]);
})
: Center(child: CircularProgressIndicator());
});
}
After adding null check (!) showing this error <the getter 'docs' is not defined for the type of object>
itemCount: snapshot.data!.docs.length,
reverse: true,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data!.docs[index];
You have to cast snapshot.data to its type. Suppose the type is QuerySnapshot (change this with the actual type of snapshot.data).
(snapshot.data! as QuerySnapshot).docs.length
Instead of typecasting at all locations, we can specify the type of stream in the StreamBuilder.
StreamBuilder<QuerySnapshot>(
...
);
Now snapshot.data is inferred as QuerySnapshot and no typecast is required.
snapshot.data!.docs.length
I have solved mine by adding StreamBuilder and builder(context, AsyncSnapshot snapshot).
Widget chatMessages() {
return StreamBuilder<QuerySnapshot>(
stream: messageStream,
builder: (context, AsyncSnapshot snapshot) {
return snapshot.hasData
? ListView.builder(
padding: EdgeInsets.only(bottom: 70, top: 16),
itemCount: snapshot.data.docs.length,
reverse: true,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.docs[index];
return chatMessageTitle(
ds["message"], myUserName == ds["sendBy"]);
})
: Center(child: CircularProgressIndicator());
});
}
There are a few solutions:
Provide a type to your StreamBuilder:
StreamBuilder<QuerySnapshot> (...)
Provide a type to the second parameter of your builder:
builder: (context, QuerySnapshot snapshot)
Use as to downcast:
(snapshot.data! as QuerySnapshot).docs['key']
Add error and connection state checks like this:
Widget chatMessages() {
return StreamBuilder(
stream: messageStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView.builder(
padding: EdgeInsets.only(bottom: 70, top: 16),
itemCount: snapshot.data.docs.length,
reverse: true,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.docs[index];
return chatMessageTitle(
ds["message"], myUserName == ds["sendBy"]);
});
});
}

Flutter/Dart Stream Builder Multiple Collections Firebase

I know there's probably a better way to do this but would like if its possible, to maintain the current DB structure.. (see attached)
DB Collections
Question: How can I return a StreamBuilder with a Listview(child:listTile) that displays profiles for all UID's that a particular user is following(eg: return user profiles that user "BHRaCBR.." is following). In this case im BHRaCBR...
Code below works but only returns one listTile (user):
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('following')
.doc('BHRaCBR..')
.collection('userFollowing')
.where('isApproved', isEqualTo: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot ds = snapshot.data.documents[index];
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('profile')
.where('uid', isEqualTo: ds['uid'])
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
final data0 = snapshot.data.docs;
return Container(
height: 200,
child: ListView.builder(
itemCount: data0.length,
itemBuilder: (BuildContext ctx, index) {
return Card(
child: ExpansionTile(
leading: CircleAvatar(
radius: 32,
backgroundImage: NetworkImage(
data0[index]
.data()['image_url']
.toString(),
),
),
title: Text(data0[index].data()['username']),
),
);
}),
);
});
});
});

Resources