web-dev-qa-db-ja.com

TextWatcherイベントが複数回発生しています

TextWatcherに迷惑な問題があります。私はウェブを検索してきましたが、何も見つかりませんでした。誰かが私を助けることができれば感謝します。

何らかの理由で、TextWatcherイベントの呼び出しが1回のテキスト変更で不安定です。ときどき、トリガーされるのは1回(そうであるように)、時には2回、時には3回です。理由はわかりませんが、全体が非常に単純です。また、afterTextChanged()のEditableパラメーターがtoString()および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ビューに変更を加えていません。

TextWatcherのイベントが2回呼び出される で質問されたのを見ましたが、イベントが2回以上(またはそれ以下)トリガーされました。

とにかく、助けを感謝します。

EDIT:afterTextChanged()の内容を削除しました。コードがなくてもこの問題が発生するためです。これがバグだと思うようになります。バグは、通常の文字の直後に「スペース」文字が入力された場合(イベントハンドラーが2回トリガーされた場合)、または通常の文字が削除された後に「スペース」文字が入力された場合(バックスペースイベントハンドラーが3回トリガーされた場合)に発生します。ヘルプはまだ感謝されます。

36
AsafK

同じ種類の問題がありました。連続テキストの最後でカーソルでバックスペースを押すと、afterTextChangeが3回呼び出されました。再び正しい値

Webで多くの検索を行った後、EditText inputTypeを

Android:inputType="textNoSuggestions"

理由を聞かないでください。しかし、うまくいきました。afterTextChangedは一度だけ呼び出されるようになりました。

52
Nico

TextWatcher の開発者ページによると、Editable内のTextWatcherに変更が加えられると、すべてのTextWatchersへのさらなる呼び出しがトリガーされます。そのEditableにリンクされています。さて、あなたのコードは明らかにこの振る舞いを引き起こしません。

ただし、何らかの理由でシステムがTextWatcherEditableを持っている場合、説明した状況が発生する可能性があります。 「なぜ」、あなたは「これが起こるべきなのか」と泣くのを聞いた。

まず、古典的な防御策:それが起こらない理由はなく、厳密には、アプリのコードはそれに抵抗力があるように書かれるべきです。

第二に、私はそれを証明することはできませんが、EditText内の表示されたテキストのレイアウトを処理するコードはTextWatcherを使用してテキストの表示の更新を処理すると想像できます。画面。このコードは、適切な改行などを保証するために、制御コード(表示されていません)をEditableに挿入する場合があります。それを正しくするためにループを数回回ることさえあります、そしてあなたはそれがすべてを終えた後に初めての呼び出しを得るかもしれません...

編集

@Learn OpenGL ESのコメントによると、TextWatcherの呼び出しはオートコレクトのようなものでは正常です。

7
Neil Townsend
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
    }
5
velraj

私にとっては、以下のコードが機能しました。 ifafterTextChangedメソッドの条件ループの後にブール値が変更されていることに注意してください

        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
            }


        });
1
shankar_vl

この質問に答えられたすべての解決策を試しましたが、私のために働いたものはありませんでした。しかし、いくつかの検索の後、私は this postを見つけました。 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);
1
Ângelo Polotto

次のようなブールチェックを使用できます。

    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;
            }
        }
    });
1
M. Usman Khan