Mon application doit afficher une liste de noms sur ListView. Ces noms sont stockés dans Nuage Fireestore de la manière suivante:
Collection: Utilisateurs - Documents: Organisé par l'utilisateur UID - Nom (Je dois noter qu'il existe également d'autres champs pour chaque utilisateur, mais j'ai besoin de récupérer le nom. Champ spécifiquement) P>
Pour ce faire, j'ai une première liste qui récupère tous les documents ou les UID utilisateur. Cette première liste est ensuite utilisée dans A pour la boucle pour récupérer le nom de chaque utilisateur de la collection Utilisateurs. P>
Toutefois, en raison de la récupération de la base de fonds de fabrication de données de manière asynchrone, certains noms sont généralement manquants et ils finissent par être affichés dans une manière désorganisée (non compatible avec l'ordre dans lequel les UID ont été transmises de la première liste). P>
Si quelqu'un pouvait me donner une idée de la manière de rendre Firebase attendre que les données soient récupérées avant de continuer avec le boucle, il serait grandement apprécié! P>
Vous trouverez ci-dessous une partie de mon code pour vous donner une meilleure idée de ce que je fais. P>
Cette première partie du code, qui récupère tout documents (UID) et les met sur une liste p> la deuxième partie du code, qui ne fonctionne pas en raison du comportement asynchrone de Firebase. P>
for (int i = 0; i<list.size(); i++) {
String uid = list.get(i);
Toast.makeText(TutorsListActivity.this, uid, Toast.LENGTH_LONG).show();
subTopicsDatabase.collection("users").document(uid).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
String stName = documentSnapshot.getString("name");
ArrayAdapter<String> adapter = new ArrayAdapter<>(TutorsListActivity.this, R.layout.item_subtopic, testList);
adapter.notifyDataSetChanged();
sListView2.setAdapter(adapter);
}
}
});
}
4 Réponses :
Votre affirmation qu'il ne fonctionne pas à cause du comportement asynchrone de Firebase est incorrecte. La raison pour laquelle votre vue n'affiche pas la façon dont vous voulez, est que vous mettez à jour votre adaptateur chaque fois que vous recevez un document de Firebase.
dans PSECUECODE, c'est ce qui devrait arriver: P> < Pré> xxx pré>
Dans une autre méthode, appelez votre méthode nouvellement créée, mettez à jour votre adaptateur avec votre liste complète de Topicnames code>. Vous pouvez également effectuer d'autres opérations sur votre tableau code> code> comme filtrage et tri. Il existe probablement une voie plus efficace également, je vous donne simplement le moyen le plus fondamental d'accomplir votre tâche. P> P>
J'ai mis à jour mon code pour ne pas mettre à jour l'adaptateur à chaque fois. Cependant, je reçois toujours le même problème, j'ai 3 noms dans ma base de données et il affiche seulement 2 sur la liste pour une raison quelconque
1.) Je double vérifier vos données pour vérifier que tout est correct. 2.) Utilisez votre débogueur pour voir quels sont les résultats de votre liste pour vos UUIDS 3.) Utilisez votre débogueur pour voir ce que les résultats de la liste de votre TopicNames sont 4.) Assurez-vous que vos données sont correctement transmises à votre adaptateur. Votre adaptateur a-t-il une méthode de mise à jour dessus? Appelez-vous notifydatastetchanged (); code> après i> vous avez mis à jour les données? À partir de ce point, vous devriez être capable de déboguer sur vous-même et de choisir l'une des réponses comme la réponse correcte.
Vous devez Comme vous avez dit // Create a Hashmap Object which has Key as UID and Name as Key
HashMap<String,String> hashMap = new HashMap<>();
for (int i = 0; i<list.size(); i++) {
final String uid = list.get(i);
Toast.makeText(TutorsListActivity.this, uid, Toast.LENGTH_LONG).show();
subTopicsDatabase.collection("users").document(uid).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists()) {
//Store Your UID and Name in Hashmap
String stName = documentSnapshot.getString("name");
hashMap.put(uid,stName);
}
//Check if it is last index of array then show the names list
if(i==list.size()-1){
showListInAdapter(hashMap);
}
}
});
}
private void showListInAdapter(HashMap<String,String> hashMap) {
//now convert your hashmap into a list of name and get Your Names List and show in Adapter
ArrayList<String> listOfNames = new ArrayList<>(hashMap.keySet());
//Set list to Adapter
ArrayAdapter<String> adapter = new ArrayAdapter<>(TutorsListActivity.this, R.layout.item_subtopic, listOfNames);
sListView2.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
HMMM approche intéressante, mais je suis toujours confronté au même problème. J'ai 3 noms dans ma base de données et cela ne s'affiche que 2 à la fin.
Je vous recommande de suivre le Guide de l'architecture de l'application et utilisez un LiveTata Observer Pour conserver la mise à jour de la liste. Vous pouvez suivre Ce tutoriel et insérer votre accès Firebase dans la classe de référentiel. P>
Changement de votre code pour s'adapter au motif MVVM peut nécessiter un peu de travail, mais il permettra également à votre application de mieux fonctionner et de simplifier le développement plus tard. P>
Vous pouvez simuler la récupération de l'utilisateur synchrone en effectuant une récursion (fonction qui l'appelait-elle jusqu'à l'index devient plus grande puis la taille de la liste des UID).
Donc, la première chose que vous souhaitez définir l'adaptateur et la liste des chaînes (qui représentent des noms d'utilisateur ). Lorsque vous faites cela, vous pouvez appeler Récursion, qui remplacera votre liste et notifiera à notifier. Voici l'exemple P>
// Define empty list of user names, which you will populate later with recursion List<String> userNames = new ArrayList<String>(); // Connect adapter with empty list ArrayAdapter<String> adapter = new ArrayAdapter<>(TutorsListActivity.this, R.layout.item_subtopic, userNames); // Set adapter to ListView sListView2.setAdapter(adapter); // Call recursion with list of uids and starting index of 0 getUserSync(list, 0); private void getUserSync(List<String> list, int i) { if (i < 0 || i > list.length - 1) { // If index i is out of bounds for list, we break the recursion return; } String uid = list.get(i); Toast.makeText(TutorsListActivity.this, uid, Toast.LENGTH_LONG).show(); subTopicsDatabase.collection("users").document(uid).get().addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() { @Override public void onSuccess(DocumentSnapshot documentSnapshot) { // When we load document, we fetch name and add it to the list which is connected to adapter // After that, we call adapter.notifyDataSetChanged which will update ui // When all that is done, we call getUserSync, to fetch user name for next uid if (documentSnapshot.exists()) { String stName = documentSnapshot.getString("name"); if (stName != null) { userNames.add(stName); adapter.notifyDataSetChanged(); } } getUserSync(list, i++); } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // If enything goes wrong, we break the recursion return; } }); }