0
votes

Y a-t-il un moyen de faire attendre mon application pour que les données soient extraites de Firebase avant de poursuivre le code?

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> xxx pré>

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);

                                }

                                }

                            });
                        }


0 commentaires

4 Réponses :


2
votes

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: < Pré> xxx

Dans une autre méthode, appelez votre méthode nouvellement créée, mettez à jour votre adaptateur avec votre liste complète de Topicnames . Vous pouvez également effectuer d'autres opérations sur votre tableau 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.


2 commentaires

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 (); après 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.



3
votes

Vous devez Stocker les éléments et enfin de la boucle de la boucle forte>, vous devez afficher la liste des noms.

Comme vous avez dit Vous obtenez une liste de tous les UID Vous voulez maintenant leurs noms sur une liste. J'avais mis à jour votre code pour travailler. P>

// 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();
    }


1 commentaires

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.



0
votes

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.

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.


0 commentaires

0
votes

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;
        }
    });
}


0 commentaires