How to retrieve the single document data and show it in app? - android

Here, I'm trying to print the username of the user and it produces the following error.
I created a function userData() and the code is
userData() async
{
var userData = await _db.collection('users').document(_uuid).get();
return userData;
}
Where I'll just get the data of the specific user using uid and returning it.
The code I used to print the data is as follow
return FutureBuilder(
future: authService.userData(),
builder: (_,snapshots){
if(snapshots.connectionState == ConnectionState.waiting)
{
return Center(child: Text('Loading...'),);
}
else{
print("Snapshots: "+snapshots.toString());
return ListView.builder(itemCount: 1, itemBuilder: (_,index){
return ListTile(
title: Text(snapshots.data["username"].toString()),
);
});
}
}
);
The structure of firestore is
Collection('user') -> document(uid) -> 1.username 2.email ....
What is the reason for this error and how to resolve it?

The error message is telling you that snapshots.data is null, so you can't index into it with the [] operator.
Before using a DocumentSnapshot, you should check to see if it exists before accessing its field data. The snapshot's data property will be null if the document doesn't exist.

For Firestore I would recommend using Stream Builder rather than future Builder.
return StreamBuilder(
stream: Firestore.instance
.collection('user')
.document(uid)
.snapshots(),
builder: (_,snapshot){
if(!snapshot.hasData)
{
return Center(child: Text('Loading...'),);
}
else{
return ListView.builder(itemCount: 1, itemBuilder: (_,index){
return ListTile(
title: Text(snapshots.data["username"].toString()),
);
});
}
}
);

Related

TypeError when converting firebase data snapshot to map

I am currently following a Flutter tutorial and the instruction states that I retrieve data from Firestore and convert to a map, the tutorial uses the code below to achieve that.
Query query = db.collection(widget.dbName).orderBy("time");
// Map the documents to the data payload
slides = query.snapshots().map((list) => list.docs.map((doc) => doc.data));
After conversion, I'm supposed to pass the value into a StreamBuilder like so
StreamBuilder(
stream: slides,
initialData: [],
builder: (context, AsyncSnapshot snap) {
List slideList = snap.data.toList();
return PageView.builder(
controller: ctrl,
itemCount: slideList.length + 1,
itemBuilder: (context, int currentIdx) {
if (currentIdx == 0) {
return _buildTagPage();
} else if (slideList.length >= currentIdx) {
bool active = currentIdx == currentPage;
return _buildStoryPage(slideList[currentIdx - 1],
active, currentIdx - 1);
} else {
return Container();
}
});
}),
The _buildStoryPage function is given below
_buildStoryPage(Map data, bool active, int index) {
//.....
//....
}
The above code returns a type error message below
type '() => Map<String, dynamic>' is not a subtype of type 'Map<dynamic, dynamic>'
I've been struggling with this since yesterday and in my research I believe the error has to be from the way the data snapshot is converted to a map but I have not been able to find a way through this error.
Assign type to your _buildStoryPage function.
_buildStoryPage(Map<String, dynamic> data, bool active, int index) {
//.....
//....
}

Query a specific document inside 2 streamBuilder

I created 2 different collections (users and follow).
Now I want to:
Fetch document which exist inside the follow's collection("list") according by their id.
Fetch users data in the first collection where currentUid = doc.id (for the second collection).
Display data in the ListTile.
First collection
await FirebaseFirestore.instance.collection("users").doc(currentUid).set({"name":username,"photoUrl":url,"uid":currentUid});
Second collection
await FirebaseFirestore.instance.collection("follow").doc(currentUid).collection("list").doc(otherId);
I used this but it doesn't work properly
body:StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("follow")
.doc(user!.uid)
.collection("list")
.snapshots(),
builder: (context, snapshot1) {
if (!snapshot1.hasData) {
return Container();
} else {
return StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("users")
.where("uid",
isEqualTo:
snapshot1.data!.docs.map((e) => e.id).toList())
.snapshots(),
builder: (context, snapshot2) {
if (!snapshot2.hasData) {
return Container();
} else {
return ListView(
children: snapshot2.data!.docs.map((e) {
return ListTile(
leading: CircleAvatar(
backgroundImage: NetworkImage(e.get('url')),
radius: 30,
),
title: Text(e.get('username')),
);
}).toList(),
);
}
},
);
You should use the in query instead of the equal to query.
An in query returns documents where the given field matches any of the
comparison values.
The syntax for the in query in the cloud_firestore is this:
.where(field, whereIn: listOfFields)
Solution:
Change this:
.where("uid", isEqualTo: snapshot1.data!.docs.map((e) => e.id).toList())
to this:
.where("uid", whereIn: snapshot1.data!.docs.map((e) => e.id).toList())

multiple list builder in flutter application

I am able to successfully create a listview.builder in flutter application as per the below code.
CODE
Container(
child: StreamBuilder<QuerySnapshot>(
stream: query2.snapshots(),
builder: (BuildContext context,AsyncSnapshot<QuerySnapshot> snapshot) {
var usernames = snapshot.data.docs.map((e) => e['itemName']);
print("usernames");
print(usernames);
if (snapshot.hasError) {
return Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Text("Loading");
}
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index){
// String itemname =snapshot.data.docs[index]['itemName'] ?? "";
return ListTile(title:Text(snapshot.data.docs[index]['itemName'] ?? ""
),);
});
}
),
)
But I want to have list view builder to be created on about 5 different if-else conditions which I am not able to do so, I tried to implement this thing on StreamBuilder but could not do it, though ternary operator works but for only two conditions at at time and not multiple conditions, how should I achieve it?
this is very simple.
if(condition1)
return Container(color:Colors.blue);
else if(condition2)
return Container(color:Colors.yellow);
else if(condition3)
return Container(color:Colors.green);
else if(condition4)
return Container(color:Colors.red);
...etc.
else
return SizedBox();

Firebase firestore queries are not filtering data, even when using where in flutter

I'm trying to use where in a Firebase firestore query in my flutter application but it is showing all the data in the collection without filtering it ., here is my code :
Widget buildingMessages() {
print('message room id $roomID'); //The correct id is being printed here
var theMessages = FirebaseFirestore.instance.collection('messages');
theMessages.where('room_id',isEqualTo: roomID).orderBy('created', descending: true);
return StreamBuilder<QuerySnapshot>(
stream: theMessages.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Something went wrong');
}
return new ListView(
children: snapshot.data.docs.map((DocumentSnapshot document) {
//....
The problem is in stream: theMessages.snapshots(). You are referencing the theMessages. and you are not using your where clause. extends it with your where clause. like
stream: theMessages.snapshots().where(
'room_id',isEqualTo: roomID).orderBy('created', descending: true);
Edit: Or initialize it as
var theMessages = FirebaseFirestore.instance.collection('messages').
where('room_id',isEqualTo: roomID).orderBy('created', descending: true);

how can i show firebase firestore data to a ResponsiveGridView() or add firestore data to a List<> in Flutter?

I can show my firebase data to a ListView.builder(). But I can't understand how can I show my data to a ResponsiveGridList().
Here is the code of MyListView.dart file where I can load firebase data
Future productData;
Future getData() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection("product").getDocuments();
return qn.documents;
}
#override
void initState() {
productData = getData();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: productData,
builder: ( _ , snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return Text("Loading...");
}else{
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index){
return ListTile( title: Text(snapshot.data[index].data["title"]),);
});
}
},
);
}
I want to use responsiveGridList() in the place of ListView.builder().
Here is the ResponsiveGridList()
List<String> list = ["title 1", "title 2", "title 3"];
ResponsiveGridList(
scroll: false,
desiredItemWidth: 200,
minSpacing: 0,
children: list.map((i) {
return Container(child: Text(i),);
}).toList()
);
I have tried to load data to my RespnsiveGridlist but can't.
Is there any option to add data to a list and then I can show the list of data into a listView.
The ResponsiveGridList() requires a list of data.

Categories

Resources