TextWatcher events are being fired multiple times
我对TextWatcher有一个烦人的问题。我一直在网上搜索,但找不到任何东西。感谢有人可以帮助我。
由于某种原因,一次文本更改后对TextWatcher事件的调用是不稳定的。有时它们会被触发一次(应该如此),有时会被触发两次,有时会被触发3次。不知道为什么,整个事情非常简单。也有时afterTextChanged()上的Editable参数在toString()和length()中返回空值。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | 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."); } }; |
在
我看到在TextWatcher的事件中提出的问题被调用了两次,但是即时事件触发的次数多于(或少于)两次。
无论如何,感谢任何帮助。
编辑:我删除了afterTextChanged()的内容,即使没有我的代码,也会出现此问题。是什么让我相信这是一个错误。当在常规字符之后立即输入"空格"字符(两次触发事件处理程序)或删除常规字符之后的"空格"字符(退格。事件处理程序被触发3次)时,就会发生此错误。帮助仍将不胜感激。
我遇到了同样的问题,当我在连续文本的末尾用光标按退格键时,afterTextChange被调用了3次:
-第一次使用正确的s值
-第二次具有明确的价值
-第三次输入正确的值
在网上搜索了很多之后,我尝试将EditText inputType更改为
1 | android:inputType="textNoSuggestions" |
不要问我为什么,但是它起作用了,afterTextChanged现在仅被调用一次。
根据TextWatcher的开发人员页面,如果对
但是,很有可能由于某种原因,如果系统在
首先,经典防御:没有理由不发生这种防御,严格来说,应编写应用程序代码以使其具有弹性。
其次,我无法证明这一点,但是我可以很好地想象一下,处理
编辑
根据@Learn OpenGL ES的评论,对于诸如自动更正之类的事情,调用TextWatcher是正常的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 } |
我尝试了所有关于此问题的解决方案,但没有一个对我有用。但是经过一番搜索,我发现了这篇文章。使用RxJava进行反跳对我来说效果很好。这是我的最终解决方案:
在Gradle文件中添加RxJava依赖项:
1 2 3 | compile 'io.reactivex:rxandroid:1.0.1' compile 'io.reactivex:rxjava:1.0.14' compile 'com.artemzin.rxjava:proguard-rules:1.0.14.2' |
实施您的主题:
1 2 3 4 5 6 | PublishSubject<String> yourSubject = PublishSubject.create(); yourSubject .debounce(100, TimeUnit.MILLISECONDS) .onBackpressureLatest() .subscribe(s -> { //Implements anything you want }); |
在TextWatcher中使用您的主题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) { } }; |
在EditText侦听器中添加TextWatcher:
1 | my_edit_text.addTextChangedListener(myTextWatcher); |
您可以使用布尔检查,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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; } } }); |
对我来说,以下代码有效。如果afterTextChanged方法中发生条件循环,请注意布尔值已更改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | edittext.addTextChangedListener(new TextWatcher() { boolean considerChange = false; public void beforeTextChanged(CharSequence cs, int start, int count, int after) {} public void onTextChanged(CharSequence cs, int start, int before, int count) {} public void afterTextChanged(Editable editable) { if (considerChange) { // your code here } considerChange = !considerChange; //see that boolean value is being changed after if loop } }); |
我的问题与此有关,因为我在模拟器中运行应用程序,并通过笔记本电脑的键盘打字(不使用模拟器的键盘),并且奇数输入将被复制。
这不是在物理设备中发生的。
从Nico的上述回答中得到了一些启发,这对我来说使输入文本更改仅触发一次就起作用了。
添加了以下输入类型配置:
1)通过风格
1 2 3 4 | <!-- in a style --> <style name="My.Text.Style"> <item name="android:inputType">text|textMultiLine|textVisiblePassword</item> </style> |
然后在xml中用作:
1 2 3 4 5 6 | <EditText android:id="@+id/my_edit_text" android:layout_width="wrap_content" android:layout_height="wrap_content" style="@style/My.Text.Style" /> |
要么
2)直接进入xml
1 2 3 4 | <EditText android:id="@+id/my_edit_text" android:inputType="text|textMultiLine|textVisiblePassword" /> |
两种方法都应该很好,这种风格只是针对想要在其他屏幕上重用它的情况。