9

New to RxJava/RxAndroid and am finding the lack of examples disturbing. As a way to jump into using Rx, id like to try to get something small working. Basically, if an EditText has text entered into it, then enable a Button below it.

I came across this answer, but the authors edit doesnt really show how to completely implement something like this.

From what I've gathered, I can use RxBindings to create an Observable like:

Observable<CharSequence> observable = RxTextView.textChanges(mEditText);

Supposedly I would now need to .subcribe() an Observer to watch for changes in observable, but am unsure how this would be done.

Also, how would you create the EditTexts Observable without using RxBindings if needed?

Edit: Although Retrolambda exists, answers showing how to implement this without lambdas (or both) would be helpful.

Community
  • 1
  • 1
Orbit
  • 2,985
  • 9
  • 49
  • 106

2 Answers2

8
Observable<CharSequence> observable = RxTextView.textChanges(mEditText);
    observable.map(new Func1<CharSequence, Boolean>() {
        @Override
        public Boolean call(CharSequence charSequence) {
            return charSequence.length() > 0;
        }
    }).subscribe(new Subscriber<Boolean>() {
        @Override
        public void onCompleted() {

        }

        @Override
        public void onError(Throwable e) {

        }

        @Override
        public void onNext(Boolean aBoolean) {
             mButton.setEnabled(aBoolean);
        }
    });

Don't forget to keep a reference to the subscription and unsubscribe when you no longer need it (eg. in onDestroy).

RxJava-Android-Samples contains RxJava examples for Android. Check it out. You might wanna check out the Form Validation example.

Also, how would you create the EditTexts Observable without using RxBindings if needed?

You can check out the implementation. It's open source. Internally it uses a TextWatcher to monitor the changes and emits items when the text changes.

LordRaydenMK
  • 13,074
  • 5
  • 50
  • 56
  • or a bit easier (still without `retrolambda`) you could use `Action1` instead of `Subscriber` – Bartek Lipinski Jan 20 '16 at 10:18
  • Forgive me but can someone please explain to me how this is "better" than just using a TextWatcher? Example doesn't even include critical functionality ("Dont forget to unsubscribe..." ) Really people? – Greg Ennis Jan 11 '17 at 14:51
  • @GregEnnis for a single `EditText` not much. The benefit is when combining multiple observables or doing some stuff on a background thread. Take a look at http://stackoverflow.com/questions/21890338/when-should-one-use-rxjava-observable-and-when-simple-callback-on-android – LordRaydenMK Jan 11 '17 at 17:04
  • @LordRaydenMK Thank you for the link. That does address the question however I'm not convinced. I left a comment on accepted answer how using kotlin operators makes rxjava way feel verbose and antiquated. kotlin is much better in many other respects as well. – Greg Ennis Jan 12 '17 at 18:31
  • @GregEnnis Kotlin does have the functional operators but they do not replace `RxJava`, it lacks the threading stuff (`subscribeOn` and `observeOn`)... also Kotlin and Java8 Streams API are pull based, RxJava is push based.... – LordRaydenMK Jan 12 '17 at 21:07
  • I guess. I'm still trying to figure out why I need rxjava, it's seems much more trouble than it's worth. I guess it's just me. – Greg Ennis Jan 13 '17 at 12:42
5

In order to subscribe to Observable<CharSequence>, you would do something like this.

Observable<CharSequence> observable = RxTextView.textChanges(mEditText).skip(1);
mButton.setEnabled(false)
observable.subscribe(mButton -> mButton.setEnabled(true));

If you're not using retrolambda, you could do something like:

Observable<CharSequence> observable = RxTextView.textChanges(mEditText).skip(1);
mButton.setEnabled(false);
observable.subscribe(new Action1<CharSequence>(){

    @Override
    public void call(CharSequence c) {
        mButton.setEnabled(true);
    }

});

As for the second part of your question: to be honest, I'm not sure but I would guess that you would add a TextWatcher on the EditText and fire an event each time the text changes (using Observable.just(charSequenceAfterEdit)).

Orbit
  • 2,985
  • 9
  • 49
  • 106
W.K.S
  • 9,787
  • 15
  • 75
  • 122
  • 1
    Meant to add, how would this be done WITHOUT lambdas? I know retrolambda exists but until its widely accepted or Java 8 comes to Android, an answer without using them would be more insightful. I'll edit the question. – Orbit Dec 23 '15 at 08:45
  • Awesome, I've edited your example to reflect the question a bit better. Hopefully ive edited the lambda part correctly. Using the `.skip()` operator waits until that number of characters has been entered, but i've noticed that if you then delete the entered characters, the button still stays enabled. Would it be trivial to make it so that the button becomes disabled again once the edittext is empty again? – Orbit Dec 23 '15 at 09:17