Java – RxTextView.textChanges using setText on Edittext

RxTextView.textChanges using setText on Edittext… here is a solution to the problem.

RxTextView.textChanges using setText on Edittext

RxTextView.textChanges(editText)
                .map(CharSequence::toString)
                .debounce(200, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(input -> {
                   output = //... do something with input
                   editText.setText(ouput)
                 }));

When I setText(output) it goes into a loop. To set up text, I first need to remove the listener and then set it up again. How do I use RxJava to do this?

Solution

When I setText(output) it goes in loop. To set the text I first need to remove listener and then set listener again. How can I do this using RxJava?

To meet the requirements, I managed to extend the RxBinding source code is as follows.

EditableTextViewTextObservable.java:

public class EditableTextViewTextObservable extends InitialValueObservable<CharSequence> {
    private final TextView view;

EditableTextViewTextObservable(TextView view) {
        this.view = view;
    }

@Override
    protected void subscribeListener(Observer<? super CharSequence> observer) {
        EditableTextViewTextObservable.Listener listener = new EditableTextViewTextObservable.Listener(view, observer);
        observer.onSubscribe(listener);
        view.addTextChangedListener(listener);
    }

@Override protected CharSequence getInitialValue() {
        return view.getText();
    }

final static class Listener extends MainThreadDisposable implements TextWatcher {
        private final TextView view;
        private final Observer<? super CharSequence> observer;

Listener(TextView view, Observer<? super CharSequence> observer) {
            this.view = view;
            this.observer = observer;
        }

@Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

@Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

@Override
        public void afterTextChanged(Editable s) {
            if (!isDisposed()) {
                view.removeTextChangedListener(this);
                observer.onNext(s);
                view.addTextChangedListener(this);
            }
        }

@Override
        protected void onDispose() {
            view.removeTextChangedListener(this);
        }
    }
}

EditableRxTextView.java:

public final class EditableRxTextView {
    @CheckResult
    @NonNull
    public static InitialValueObservable<CharSequence> textChanges(@NonNull TextView view) {
        return new EditableTextViewTextObservable(view);
    }
}

Usage:

EditableRxTextView.textChanges(editText)
            .map(CharSequence::toString)
            .debounce(200, TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(input -> {
               output = //... do something with input
               editText.setText(ouput)
             }));

Related Problems and Solutions