TextWatcher événements déclenchés plusieurs fois
J'ai un problème ennuyeux avec TextWatcher. j'ai cherché sur le web, mais je n'ai rien trouvé. reconnaissant si quelqu'un pouvait m'aider.
pour une raison quelconque, les appels aux événements TextWatcher après un changement de texte sont erratiques. parfois ils sont déclenchés une fois (comme ils devraient l'être), parfois deux fois, et parfois trois fois. n'ai aucune idée de pourquoi, le tout est très simple. parfois aussi le modifiable le paramètre on afterTextChanged() renvoie les valeurs vides dans toString () et length ().
code ci-dessous:
private TextWatcher mSearchAddressTextChangeListener = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
@Override
public void afterTextChanged(Editable searchedAddress) {
System.out.println("called multiple times.");
}
};
à l'intérieur afterTextChanged()
(et le AsyncTask
) je ne suis pas le fait de modifier le texte ou le EditText
.
j'ai vu la question posée dans les événements de TextWatcher sont appelés deux fois , mais im ayant les événements déclenchés plus (ou moins) que deux fois.
de toute façon, j'apprécie toute aide.
EDIT: j'ai supprimé le contenu de afterTextChanged() car ce problème se produit même sans mon code. ce qui m'amène à croire que c'est un bug. Le bogue se produit lorsqu'un caractère' space 'est entré juste après un caractère régulier (les gestionnaires d'événements sont déclenchés deux fois) ou lorsqu'un caractère' space ' après un caractère régulier est supprimé (backspace. les gestionnaires d'événements sont déclenchés 3 fois). l'aide sera toujours apprécié.
5 réponses
j'ai eu le même genre de problème, quand j'ai pressé backspace avec curseur à la fin d'un texte continu, afterTextChange a été appelé 3 fois: - La première fois avec la bonne valeur - La deuxième fois avec une valeur précise - La troisième fois avec la valeur correcte à nouveau
après avoir cherché beaucoup sur le web, j'ai essayé de changer mon entrée de texte en
android:inputType="textNoSuggestions"
ne me demandez pas pourquoi, mais cela a fonctionné, après que TeX-modified est maintenant appelé seulement lorsque.
selon les pages du développeur pour TextWatcher , si un changement est fait au Editable
dans TextWatcher
, il déclenchera d'autres appels à tous les TextWatchers
lié à celui Editable
. Il est clair que votre code ne déclenche pas ce comportement.
cependant, il est tout à fait possible que si, pour une raison quelconque , le système a un TextWatcher
sur le Editable
, la situation que vous décrivez peut se produire. "Pourquoi", je t'entends pleurer, "si cela arrive?"
tout d'abord, la défense classique: il n'y a aucune raison pour que cela n'arrive pas et, à strictement parler, le code app doit être écrit pour être résistant à lui.
deuxièmement, je ne peux pas le prouver, mais je pourrais bien imaginer que le code qui gère la disposition du texte affiché dans un EditText
utilise un TextWatcher
pour gérer la mise à jour de l'affichage du texte sur l'écran. Ce code peut insérer des codes de contrôle (qui ne sont pas affichés) dans Editable
pour assurer une bonne rupture de ligne et ainsi de suite. Il peut même faire le tour d'une boucle à quelques reprises pour l'obtenir correctement, et vous pourriez seulement obtenir votre premier appel après qu'il a fait tout le sien ...
EDIT
selon le commentaire de @Learn, l'appel D'un TextWatcher serait normal pour des choses comme autocorrect.
boolean isOnTextChanged = false;
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
isOnTextChanged = true;
}
@Override
public void afterTextChanged(Editable quantity) {
if (isOnTextChanged) {
isOnTextChanged = false;
//dosomething
}
u peut utiliser un contrôle booléen, comme:
inputBoxNumberEt.addTextChangedListener(new TextWatcher() {
boolean ignoreChange = false;
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (!ignoreChange) {
///Do your checks
ignoreChange = true;
inputBoxNumberEt.setText(string);
inputBoxNumberEt.setSelection(inputBoxNumberEt.getText().length());
ignoreChange = false;
}
}
});
j'ai essayé toute la solution répondu à cette question, aucun de ceux travaillé pour moi. Mais après quelques recherches j'ai trouvé ce "post 151960920". Utiliser le RxJava pour faire le debounce a bien fonctionné pour moi. Voici ma solution finale:
ajouter les dépendances de RxJava dans le fichier Gradle:
compile 'io.reactivex:rxandroid:1.0.1'
compile 'io.reactivex:rxjava:1.0.14'
compile 'com.artemzin.rxjava:proguard-rules:1.0.14.2'
mettre en œuvre votre sujet:
PublishSubject<String> yourSubject = PublishSubject.create();
yourSubject .debounce(100, TimeUnit.MILLISECONDS)
.onBackpressureLatest()
.subscribe(s -> {
//Implements anything you want
});
utilisez votre sujet dans votre TextWatcher:
TextWatcher myTextWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
yourSubject.onNext(s.toString()); //apply here your subject
}
@Override
public void afterTextChanged(Editable s) {
}
};
ajouter le TextWatcher dans L'auditeur EditText:
my_edit_text.addTextChangedListener(myTextWatcher);