$30 off During Our Annual Pro Sale. View Details »

Introduction to RxJava for Android

Esa Firman
October 23, 2015

Introduction to RxJava for Android

Esa Firman

October 23, 2015
Tweet

More Decks by Esa Firman

Other Decks in Technology

Transcript

  1. Introduction to RxJava for Android
    Esa Firman

    View Slide

  2. What is RxJava?
    RxJava is a Java VM implementation of ReactiveX (Reactive
    Extensions): a library for composing asynchronous and
    event-based programs by using observable sequences
    See also: 2 minutes introduction to Rx
    https://medium.com/@andrestaltz/2-minute-introduction-to-rx-24c8ca793877#.rwup8ee0s

    View Slide

  3. The Problem
    How to deal with execution context ?

    View Slide

  4. Threads
    Handler handler = new Handler(Looper.getMainLooper());
    new Thread(){
    @Override
    public void run() {
    final String result = doHeavyTask();
    handler.post(new Runnable() { // or runUIThread on Activity
    @Override
    public void run() {
    showResult(result);
    }
    });
    }
    }.start();

    View Slide

  5. Threads
    Pros:
    - Simple
    Cons:
    - Hard way to deliver results in UI thread
    - Pyramid of Doom

    View Slide

  6. AsyncTask
    new AsyncTask(){
    @Override
    protected String doInBackground(Void... params) {
    return doHeavyTask();
    }
    @Override
    protected void onPostExecute(String s) {
    showResult(s);
    }
    }.execute();

    View Slide

  7. AsyncTask
    Pros:
    - Deal with main thread
    Cons:
    - Hard way to handling error
    - Not bound to activity/fragment lifecycle
    - Not composable
    - Nested AsyncTask
    - “Antek Async”

    View Slide

  8. Why Rx?
    - Because multithreading is hard
    - Execution context
    - Powerful operators
    - Composable
    - No Callback Hell
    - Etc ...

    View Slide

  9. The Basic
    The basic building blocks of reactive code are Observables
    and Subscribers. An Observable emits items; a Subscriber
    consumes those items.
    The smallest building block is actually an Observer, but in practice you are most often using Subscriber because that's how
    you hook up to Observables.

    View Slide

  10. The Basic
    Observables often don't start emitting items until someone
    explicitly subscribes to them

    View Slide

  11. Enough talk, let’s see some code ...

    View Slide

  12. Hello World
    public Observable getStrings() {
    return Observable.create(new Observable.OnSubscribe() {
    @Override
    public void call(Subscriber super String> subscriber) {
    try {
    subscriber.onNext("Hello, World");
    subscriber.onCompleted();
    } catch (Exception ex) {
    subscriber.onError(ex);
    }
    }
    });
    }

    View Slide

  13. Hello World
    getStrings().subscribe(new Subscriber(){
    @Override
    public void onCompleted() {
    // no - op
    }
    @Override
    public void onError(Throwable e) {
    e.printStackTrace();
    }
    @Override
    public void onNext(String s) {
    System.out.println(s);
    }
    };

    View Slide

  14. Observable myObservable = Observable.just("Hello, world!");
    Action1 onNextAction = new Action1<>() {
    @Override
    public void call(String s) {
    System.out.println(s);
    }
    };
    myObservable.subscribe(onNextAction);
    // Outputs "Hello, world!"
    Simpler Code

    View Slide

  15. Simplest* Code - Using Lambda
    Observable.just("Hello, World").subscribe(System.out::println);
    *AFAIK

    View Slide

  16. Observable Creation
    Observable.create(Observable.onSubscribe)
    from( ) — convert an Iterable or a Future or single value into an Observable
    repeat( ) — create an Observable that emits a particular item or sequence of items repeatedly
    timer( ) — create an Observable that emits a single item after a given delay
    empty( ) — create an Observable that emits nothing and then completes
    error( ) — create an Observable that emits nothing and then signals an error
    never( ) — create an Observable that emits nothing at all

    View Slide

  17. Operators

    View Slide

  18. Filtering Operators
    - filter( ) — filter items emitted by an Observable
    - takeLast( ) — only emit the last n items emitted by an Observable
    - takeLastBuffer( ) — emit the last n items emitted by an Observable, as a single list item
    - skip( ) — ignore the first n items emitted by an Observable
    - take( ) — emit only the first n items emitted by an Observable
    - first( ) — emit only the first item emitted by an Observable, or the first item that meets some condition
    - elementAt( ) — emit item n emitted by the source Observable
    - timeout( ) — emit items from a source Observable, but issue an exception if no item is emitted in a
    specified timespan
    - distinct( ) — suppress duplicate items emitted by the source Observable

    View Slide

  19. View Slide

  20. Filter
    Observable.just("Esa", "Ganteng", "Jelek")
    .filter(s -> !s.equalsIgnoreCase("jelek"))
    .buffer(2)
    .subscribe(strings -> {
    print(strings.get(0) + “ “ + strings.get(1));
    });
    // print Esa Ganteng

    View Slide

  21. Transformation Operators
    - map( ) — transform the items emitted by an Observable by applying a function to each of them
    - flatMap( ) — transform the items emitted by an Observable into Observables, then flatten this into a
    single Observable
    - scan( ) — apply a function to each item emitted by an Observable, sequentially, and emit each
    successive value
    - groupBy( ) and groupByUntil( ) — divide an Observable into a set of Observables that emit groups of
    items from the original Observable, organized by key
    - buffer( ) — periodically gather items from an Observable into bundles and emit these bundles rather
    than emitting the items one at a time
    - window( ) — periodically subdivide items from an Observable into Observable windows and emit these
    windows rather than emitting the items one at a time

    View Slide

  22. View Slide

  23. Map
    Observable.from(Arrays.asList("Esa", "Esa", "Esa"))
    .map(s -> s + " ganteng")
    .subscribe(System.out::println);
    // print Esa ganteng 3 times

    View Slide

  24. View Slide

  25. FlatMap
    Observable.just( Arrays.asList("Tiramisu", "Black Forest", "Black Mamba"))
    .flatMap(Observable::from)
    .map(String::length)
    .subscribe(System.out::print);
    // print 8,11,12

    View Slide

  26. Confused?
    Getting map/flatMap/compose mixed up? Think types:
    map : T -> R
    flatMap : T -> Observable
    compose : Observable -> Observable
    #ProTips

    View Slide

  27. Retrofit Integration
    @GET("mobile_detail_calc_halte_trans.php")
    Observable>
    getHalteDetails(@Query("coridor") String coridor);
    mApiService.getHalteDetails(halte.getCoridor())
    .observeOn(AndroidSchedulers.mainThread())
    .doOnTerminate(this::resetUILoading)
    .subscribe(halteDetails -> {
    if (halteDetails != null) {
    setMarker(halteDetails);
    }
    });

    View Slide

  28. More Examples
    mApiService.getCommentList()
    .compose(bindToLifecycle())
    .compose(applyApiCall())
    .doOnTerminate(this::stopLoading)
    .subscribe(comments -> {
    if (comments != null)
    mCommentAdapter.pushData(comments);
    });

    View Slide

  29. More Samples
    Observable imageObservable = Observable.create(observer -> {
    Bitmap bm = downloadBitmap();
    return bm;
    });
    imageObservable.subscribe(image -> loadToImageView(image));
    // blocking the UI thread
    imageObservable
    .subscribeOn(Schedulers.newThread())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(image -> loadToImageView(image));
    // non blocking but also execute loadToImageView on UI Thread

    View Slide

  30. More Examples
    public Observable> getAreas() {
    Observable> network = mApiService.getArea()
    .observeOn(AndroidSchedulers.mainThread())
    .doOnNext(areas -> saveAreas(areas));
    Observable> cache = getAreasFromLocal();
    return Observable.concat(cache, network).first(areas -> areas != null);
    }

    View Slide

  31. More Examples (Again)
    public void onLocationChanged(Location location) {
    onLocationChanged.onNext(location);
    }
    mGmsLocationManager.onLocationChanged
    .throttleLast(10, TimeUnit.SECONDS)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(location -> {
    mPrensenter.updateMyLocation(location);
    });

    View Slide

  32. FAQ
    1. Should we still use Thread and AsyncTask?
    2. Where to start?

    View Slide

  33. Third Party Implementation
    - Android ReactiveLocation
    https://github.com/mcharmas/Android-ReactiveLocation
    -
    RxPermissions
    https://github.com/tbruyelle/RxPermissions
    - RxBinding
    https://github.com/JakeWharton/RxBinding
    - SQLBrite
    https://github.com/square/sqlbrite
    - RxLifeCycle
    https://github.com/trello/RxLifecycle

    View Slide

  34. Links
    - http://slides.com/yaroslavheriatovych/frponandroid
    - https://github.com/Netflix/RxJava/
    - https://github.com/orfjackal/retrolambda
    - https://github.com/evant/gradle-retrolambda
    - http://cr.openjdk.java.net/~briangoetz/lambda/lambda-translation.html
    - https://github.com/Netflix/RxJava/wiki

    View Slide

  35. Questions?

    View Slide