I am building a quiz app using Flutter and Firebase Firestore. I want to display the rank of the current user in the app. So, I am getting all the user docs in descending order of their respective scores. Now from this list of docs I want the index of the current user's document, which is also the rank of the user.
I am getting all the docs in descending order of their scores like this :
final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance
.collection('users')
.orderBy('totalScore', descending: true)
.snapshots();
Now how do I get the index of the current user's document present in the list of all docs retrieved? I want to use Streambuilder to display the rank.
This is my Firestore database:
UPDATE:
So I tried iterating the fetched documents to get the index where uid is equal to the document's name.
First I have defined a method foorloop()
forloop(
int rank,
var data,
String? uid,
) async {
for (int i = 0; i < data.length; i ) {
if (uid == data[i].toString()) {
rank = i;
}
}
return rank;
}
This method takes 'data' which is the list of docs from firestore fetched in descending order of scores, and 'uid' which is the current user uid. It iterates the list and returns 'rank' which is the index where uid is equal to the document name.
I called this method in a Text Widget to display the rank but it displays a text which says "Instance of 'Future'". I need it to display the expected index. How do I solve this?
StreamBuilder<QuerySnapshot>(
stream: _usersStream,
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(
color: Colors.deepPurple,
),
);
}
var data = snapshot.data!.docs;
int rank = 0;
return Text(
forloop(rank, data, uid).toString()
);
},
CodePudding user response:
So I finally got it.
I defined a method getRank which iterates the document list and returns the index where document id is equal to the uid of current user. Before I was using data[i] in the if condition instead of data[i].reference.id which gives the document id.
getRank(
int rank,
var data,
String? uid,
) {
for (int i = 0; i < data.length; i ) {
if (uid == data[i].reference.id) {
rank = i 1;
}
}
return rank;
}
Now I used this method in Streambuilder
StreamBuilder<QuerySnapshot>(
stream: stream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return const Text('Something went wrong');
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(
color: Colors.deepPurple,
),
);
}
var data = snapshot.data!.docs;
int rank = 0;
return Text(
getRank(rank, data, uid).toString(),
);
},
);
Here stream is :
final Stream<QuerySnapshot> stream = FirebaseFirestore.instance
.collection('users')
.orderBy('totalScore', descending: true)
.snapshots();