1

J'ai une liste d'étiquettes stockées dans Firebase. Dans l'un de mes Fragments, un MultiAutoCompleteTextView (MACTV) permet à l'utilisateur de sélectionner les tags pertinents.MultiAutoCompleteTextView et Firebase

L'objectif,

  • est de peupler l'Array (utilisé dans ArrayAdapter pour MACTV) en utilisant les tags de Firebase.
  • Une fois que l'utilisateur sélectionne les variables pertinentes de MACTV à l'aide de OnItemClickListener, les variables sélectionnées doivent être enregistrées dans Firebase.

Voici comment j'ai essayé d'implémenter.

Définition du ArrayAdapter pour MACTV:

ArrayAdapter<String> adapterMultiAutoComplete = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1); 

Utilisation du AddValueEventListener pour alimenter le ArrayAdapter

if (fbUser != null) { 
    dbTags.addValueEventListener(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
     //Basically, this says "For each DataSnapshot *Data* in dataSnapshot, do what's inside the method. 
      for (DataSnapshot tagNameSnapshot : dataSnapshot.getChildren()) { 
      //Get the suggestion by childing the key of the string you want to get. 
       String ValueTagName = tagNameSnapshot.child("tagName")).getValue(String.class); 
      //Add ValueTagName to ArrayAdapter 
       adapterMultiAutoComplete.add(ValueTagName); 
      } 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) {/*Do Nothing*/} 
    }); 
} 

Code pour MACTV

MultiAutoCompleteTextView articleTags = (MultiAutoCompleteTextView) findViewById(R.id.mactv_tags); 
articleTags.requestFocus(); 
articleTags.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer()); 
articleTags.setAdapter(adapterMultiAutoComplete); 

Enregistrer les balises sélectionnées pour Firebase

List<String> ArticleTags = new ArrayList<>(Arrays.asList(articleTags.getText().toString().split(", "))); 
DatabaseReference db = FirebaseDatabase.getInstance().getReference().child("tags").setValue(ArticleTags); 

La valeur seuil est définie comme 2. Malheureusement, aucune balise pertinentes apparaissent comme pop-up quand je commence à taper MACTV.

Où est-ce que je me suis trompé?

+0

Ajoutez simplement cette ligne dans la méthode onDataChange() après avoir ajouté un élément à l'adaptateur. adapterMultiAutoComplete.notifyDataSetChanged(); –

+0

Question connexe (pas en double) avec réponse http://stackoverflow.com/a/39715702/5593959 –

Répondre

1

BTW, bonne question! Le plus intéressant que j'ai vu ce mois-ci. Tout d'abord, avec ce code, vous chargez l'intégralité du nœud tags sur l'équipement. Imaginez, vous avez 2M de balises (est-ce que SO a?), Ce code fonctionnera-t-il encore? La deuxième chose, le code onDataChange (ainsi que le code dans tous les rappels Firebase) est appelé sur le thread de travail, mais les méthodes de l'adaptateur doivent être appelées dans le thread de l'interface utilisateur.

Et le dernier, voici comment je vois la solution:

  1. Vous devez utiliser des requêtes (vous pouvez lire plus docs)
  2. Tout d'abord, nous devons trier les balises par nom . C'est donc la requête de base:

    DatabaseReference baseRef = FirebaseDatabase.getInstance().getReference().child("tags").orderByChild("tagName"); 
    
  3. Suivant - vous devez joindre à votre TextWatcherMultiAutoCompleteTextView avec le code suivant

    articleTags.addTextChangedListener(new TextWatcher() { 
    
        @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {} 
    
        @Override 
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { 
    
         if (charSequence.length <3) return; 
    
         String searchTarget = charSequence.toString().toLowerCase(); 
         //Here magic happens) 
         baseRef.startAt(searchTarget).endAt(searchTarget + "\uf8ff").limitToFirst(20).addValueEventListener(new ValueEventListener() { 
          @Override 
          public void onDataChange(DataSnapshot dataSnapshot) { 
           //Handle executing this code in main thread yourself, answer will be too long with it 
           adapterMultiAutoComplete.removeAll(); 
           for (DataSnapshot data: dataSnapshot.getChildren()) { 
            adapterMultiAutoComplete.add(data.getValue(String.class)) 
           } 
           adapterMultiAutoComplete.notifyDatasetChanged(); 
          } 
    
          @Override 
          public void onCancelled(DatabaseError databaseError) { 
           Log.wtf("What a terrible failure!", databaseError.toException()); 
          } 
         }); 
    
        } 
    
        @Override public void afterTextChanged(Editable editable) {} 
    
    }); 
    

P.S .: code n'a jamais été testé et probablement ne fonctionne pas.Mais vous avez l'idée;)

+0

Merci d'avoir présenté la perspective alternative à la solution. Je n'ai pas pensé à utiliser des requêtes plus tôt. Mais quel est le meilleur moyen? _Case 01: _ Utilisation de la boucle For pour récupérer tous les tagsNames disponibles. Dans ce cas, l'avantage est de faire des recherches plus rapides, mais cela n'a pas de sens quand on implique trop de balises. Dans _Case 02: _ (en utilisant des requêtes), trop de temps de recherche est impliqué (disons quand je souhaite rechercher et ajouter dix balises) – user3314337

+0

@ user3314337 Définir la limite à 100, par exemple. Si vous avez moins de 100 valeurs, enregistrez-les dans l'adaptateur et ne faites pas plus de requêtes =) –