Skip to content

Instantly share code, notes, and snippets.

@mkodekar
Forked from cesarferreira/RxJava.md
Created September 20, 2016 10:56
Show Gist options
  • Save mkodekar/c83547d19a5750ee2900ad8c9dccd47d to your computer and use it in GitHub Desktop.
Save mkodekar/c83547d19a5750ee2900ad8c9dccd47d to your computer and use it in GitHub Desktop.
Party tricks with RxJava, RxAndroid & Retrolambda

View Click

Instead of the verbose setOnClickListener:

RxView.clicks(submitButton).subscribe(o -> log("submit button clicked!"));

Filter even numbers

Observable
    .just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .filter(integer -> integer % 2 == 0)
    .subscribe(System.out::println);

    // => 2, 4, 6, 8, 10

Iterating with "forEach"

Observable
    .just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .forEach(System.out::println);

    // => 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

Group by

Observable
    .just(1, 2, 3, 4, 5)
    .groupBy(integer -> integer % 2 == 0).subscribe(grouped -> {
        grouped.toList().subscribe(integers -> {
            log(integers + " (Even: " + grouped.getKey() + ")");
        });
    });

    // [1, 3, 5] (Even: false)
    // [2, 4] (Even: true)

Take only the first N values emitted

Observable
    .just(1, 2, 3, 4, 5)
    .take(2)
    .subscribe(System.out::println);

    // => 1, 2

First

Observable
    .just(1, 2, 3, 4, 5)
    .first()
    .subscribe(System.out::println);

    // => 1

Last

Observable
    .just(1, 2, 3, 4, 5)
    .last()
    .subscribe(System.out::println);

    // => 5

Distinct

Observable
    .just(1, 2, 1, 3, 4, 2)
    .distinct()
    .subscribe(System.out::println);

    // => 1, 2, 3, 4

Map()

Does not have to emit items of the same type as the source Observable

Observable.just("Hello world!")
    .map(s -> s.hashCode())
    .subscribe(i -> log(Integer.toString(i)));

    // => 121287312

Another map() can convert it back to String

Observable.just("Hello world!")
    .map(s -> s.hashCode())
    .map(i -> reverseHashCode(i))
    .subscribe(str -> log(str));

    // => Hello world!

Iterate an array list

List<User> users = ArrayList<>();

users.add(new User("jon snow"));
users.add(new User("tyrion lannister"));

Observable
    .just(users)
    .concatMap(userList -> Observable.from(userList))
    .subscribe(user -> log(user.name));

    // concatMap: when applied to an item emitted by the source Observable, returns an Observable

    // => "jon snow", "tyrion lannister"

Observe text changes on an EditText (RxBinding)

 RxTextView.textChangeEvents(editText)
   .subscribe(e -> log(e.text().toString()));

    // => "s"
    // => "se"
    // => "sea"
    // => "sear"
    // => "searc"
    // => "search"

Filter text changes on an EditText (RxBinding)

 RxTextView.textChangeEvents(editText)
    .filter(e -> e.text.length() >= 3)
    .subscribe(e -> log(e.text().toString()));

    // => "sea"
    // => "sear"
    // => "searc"
    // => "search"

Login form (RxBinding)

The submit button only gets enabled if username and password have a length>=3

    emailChangeObservable = RxTextView.textChangeEvents(email);
    passwordChangeObservable = RxTextView.textChangeEvents(password);

    // force-disable the button
    submitButton.setEnabled(false);

    Observable.combineLatest(emailChangeObservable, passwordChangeObservable, 
                                            (emailObservable, passwordObservable) -> {
        boolean emailCheck = emailObservable.text().length() >= 3;
        boolean passwordCheck = passwordObservable.text().length() >= 3;
        return emailCheck && passwordCheck;
    }).subscribe(aBoolean -> {
        submitButton.setEnabled(aBoolean);
    });

    // submit button will only be clickable if both forms have more than 3 characters each

Thread safety (RxJava + RxAndroid + Retrolambda)

Observable
    .just(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .flatMap(this::heavyCalculations)
    // all the computation will happen in a background thread
    .subscribeOn(Schedulers.computation())
    // the result subscription will happen in the UI Thread
    .observeOn(AndroidSchedulers.mainThread())
    // do the calculations for each item and returns it to the subscribable observer
    .subscribe(number -> log(number));

Persist data async to the database (RxJava + RxAndroid + Retrolambda)

Observable
    .just(arrayOfUsers)
    .concatMap(users1 -> Observable.from(users1))
    .doOnNext(user -> saveToDataBase(user))
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe();

    // => saves all the users, one by one in the database, async

Pro-tip

Don't know in which thread your code is being executed? Print this method:

Thread.currentThread().getName()

and you'll find out.

Note

All subscribe()s return a Subscription object that should be released with a subscription.unsubscribe() in the activity/fragment lifecycle to prevent memory leaks.

... or if you're lazy like me take a look here https://github.com/trello/RxLifecycle, the guys @trello have created a library that provides automatic unsubscriptions to this kind of events.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment