2016-11-13 8 views
2

Je suis nouveau à Rx monde et essayer de mettre en œuvre mon AutoCompleteTextView avec RxJava, RxBinding et Retrofit 2.AutoCompleteTextView avec 2 Rénovation, RxJava et RxBinding

Voici ce que je viens avec ce qui est gênant: (. Peut-être que je ne le fais pas dans le droit chemin)

J'ai un AutoCompleteTextView et ici je créé mon Abonnez-vous et observables:

subcription = RxTextView.textChangeEvents(clearableEditText) 
       .skip(1) 
       .debounce(400, TimeUnit.MILLISECONDS) 
       .map(new Func1<TextViewTextChangeEvent, String>() { 
        @Override 
        public String call(TextViewTextChangeEvent textViewTextChangeEvent) { 
         return textViewTextChangeEvent.text().toString(); 
        } 
       }) 
       .filter(new Func1<String, Boolean>() { 
        @Override 
        public Boolean call(String s) { 
         return s.length() > 2; 
        } 
       }) 
       .flatMap(new Func1<String, Observable<List<String>>>() { 
        @Override 
        public Observable<List<String>> call(String text) { 
         return searchService.getAutoCompleteTermsObservable(text) 
           .subscribeOn(Schedulers.io()) 
           .observeOn(AndroidSchedulers.mainThread()); 
        } 
       }) 
       .observeOn(AndroidSchedulers.mainThread()) 
       .subscribe(new Subscriber<List<String>>() { 
        @Override 
        public void onCompleted() { 
         Log.d("rx", "oncomplete"); 
        } 

        @Override 
        public void onError(Throwable e) { 
         Log.e("rx", e.toString()); 
        } 

        @Override 
        public void onNext(List<String> strings) { 
         Log.d("rx", strings.size()+""); 
         autoAdapter = new ArrayAdapter<>(MainActivity.this, 
           android.R.layout.simple_dropdown_item_1line, strings); 
         clearableEditText.setAdapter(autoAdapter); 
         clearableEditText.showDropDown(); 
        } 
       }); 

Mon problème est lorsque je mets mon EditText avec la méthode setText(), il déclenche la liste déroulante. Par exemple, il le fait quand je mets le mot de la liste déroulante AutoCompleteTextView et quand je le mets avec une entrée vocale. Y at-il un moyen d'éviter de déclencher onTextChanged lorsque je l'ai défini manuellement? Ou comment puis-je résoudre ce problème?

+2

Le problème est que, lorsque vous définissez le texte, l'observable émet l'événement, essayez de vous désabonner avant de définir le texte et de vous abonner à nouveau après cela. – AndroidRuntimeException

+0

Oui, simple comme ça! Merci @Agustin Sivoplás. –

+0

Content de vous aider! Bonne chance! – AndroidRuntimeException

Répondre

1

Vous pouvez en effet utiliser unsubscribe() mais selon la façon dont vous définissez la valeur, vous utilisez également skipWhile. Voici un exemple:

public void handleTextChanges() { 
    final String textFromSource = "an"; 

    Observable.fromArray("a", "an", "ancestor") 
      .skipWhile(new Predicate<String>() { 
       @Override 
       public boolean test(String value) throws Exception { 
        return textFromSource.contains(value); 
       } 
      }) 
      .subscribe(new Consumer<String>() { 
       @Override 
       public void accept(String value) throws Exception { 
        Log.d("Rx", value); 
       } 
      }); 
} 

Ce ne consommera que ancestor (exemple RxJava2, mais les mêmes méthodes existent). Toutes les valeurs suivantes, même si elles correspondent à an, seront consommées. Vous pouvez utiliser filter si vous voulez toujours faire le contrôle comme ceci

+0

Merci pour l'approche alternative @Jordy Langen. Cependant, celui-ci ne fait-il pas une requête réseau non-nécessaire? –

+0

Pas aussi longtemps que la première valeur véridique a été trouvée dans 'skipWhile' –

+0

Lorsque je sélectionne un élément dans la liste déroulante Saisie semi-automatique, il appellera setText avec cette valeur et parce qu'il déclenche onTextChange, il ne fera qu'une seule requête pour obtenir des suggestions de saisie semi-automatique et avec skipWhile, la liste déroulante ne sera pas affichée. Même avec la saisie vocale, j'appelle setText, cette fois-ci il peut ou non correspondre à cela mais dans ces cas, la liste déroulante ne sera pas affichée. Oui, en fait, cette approche semble être plus propre que ma méthode setTextSafely(). Et j'appelle cette méthode dans plusieurs endroits, donc si je veux faire autocompléter une préférence d'utilisateur, votre chemin me donnera de la flexibilité. Merci, @Jordy Langen –