首页 文章

TextWatcher事件被多次触发

提问于
浏览
28

我对TextWatcher有一个恼人的问题 . 我一直在网上搜索,但找不到任何东西 . 感谢有人能帮助我 .

For some reason the calls to the TextWatcher events upon one text change are erratic. sometimes they are being triggered once (like they should be), sometimes twice, and sometimes 3 times. have no idea why, the whole thing is very straight forward. also sometimes the Editable parameter on afterTextChanged() returns empty values in toString() and length().

代码如下:

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

afterTextChanged() (和 AsyncTask )里面我没有对文本或 EditText 视图进行任何更改 .

我在Events of TextWatcher are being called twice中看到了问题,但即时通讯触发的事件多于(或少于)两次 .

无论如何,感谢任何帮助 .

EDIT: 我删除了afterTextChanged()的内容,导致即使没有我的代码也会发生此问题 . 是什么让我相信这是一个错误 . 在常规字符(事件处理程序被触发两次)之后立即输入'space' char或在删除常规字符之后输入'space'字符(退格 . 事件处理程序被触发3次)时,会发生错误 . 帮助仍将受到赞赏 .

5 回答

  • 7

    我有同样的问题,当我在连续文本的末尾用光标按下退格键时,afterTextChange被调用3次: - 第一次使用正确的s值 - 第二次使用清除值 - 第三次使用再次正确的值

    在网上搜索了很多之后,我尝试将EditText inputType更改为

    android:inputType="textNoSuggestions"
    

    不要问我为什么,但它有效,afterTextChanged现在只调用一次 .

  • 1

    根据TextWatcher的开发者页面,如果在 TextWatcher 内对 Editable 进行了更改,则会触发对该 Editable 链接的所有 TextWatchers 的进一步调用 . 现在,显然您的代码不会触发此行为 .

    但是,如果由于某种原因系统在 Editable 上有 TextWatcher ,很可能会出现您所描述的情况 . "Why",我听你哭了,"should this happen?"

    首先,经典防御:没有理由不发生,严格来说,应该编写应用程序代码以适应它 .

    其次,我无法证明这一点,但我可以想象处理 EditText 中显示文本布局的代码使用 TextWatcher 来处理更新屏幕上文本的显示 . 此代码可能会将控制代码(未显示)插入 Editable 以确保良好的换行符等 . 它甚至可以循环几次以使其正确,并且您可能只有在完成所有操作后才能进行第一次调用...

    编辑

    根据@Learn OpenGL ES的评论,调用TextWatcher对于自动更正这样的事情是正常的 .

  • 3
    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
        }
    
  • 48

    你可以使用布尔检查,如:

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

    我尝试了在这个问题上回答的所有解决方案,这些都没有为我工作 . 但经过一番搜索,我找到了this帖子 . 使用RxJava进行去抖动对我来说效果很好 . 这是我的最终解决方案:

    在Gradle文件中添加RxJava依赖项:

    compile 'io.reactivex:rxandroid:1.0.1'
    compile 'io.reactivex:rxjava:1.0.14'
    compile 'com.artemzin.rxjava:proguard-rules:1.0.14.2'
    

    实施您的主题:

    PublishSubject<String> yourSubject = PublishSubject.create();
        yourSubject .debounce(100, TimeUnit.MILLISECONDS)
                .onBackpressureLatest()
                .subscribe(s -> {
                    //Implements anything you want
                });
    

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

    在EditText侦听器中添加TextWatcher:

    my_edit_text.addTextChangedListener(myTextWatcher);
    

相关问题