Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Reactive programming on android...

Introduction to Reactive programming on android - Droidcon Vietnam, April 2017

Soham Mondal

April 16, 2017
Tweet

More Decks by Soham Mondal

Other Decks in Technology

Transcript

  1. Soham Mondal / @s0h4m Founder Triveous, Skyro Organizer, Google Developer

    Expert Blrdroid Android/UX Consultant EnParadigm, Khoslalabs, Hiree, Farmily
  2. Example Travel app: User is looking for good hotels in

    the current location Screenshots are from the bookin.com android app.
  3. Travel App - Find location Asynchronously - Find user details

    Asynchronously - Once you have location, make a network call for a list of all hotels in the area for that user - Make a separate api call for each hotel to check for a) availability and b) price and c) ratings - Dynamically filter hotels based on preference - Update data as soon as it arrives
  4. About RxJava - Rx: Reactive Extensions - Functional Reactive programming

    - From the good folks at Microsoft - Erik Meijer on the Microsoft .NET platform - Notoriously difficult to approach - also on .net, javascript, scala, kotlin, clojure, you get the picture
  5. Functional Programming In computer science, functional programming is a programming

    paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions. In functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) each time. Eliminating side effects, i.e. changes in state that do not depend on the function inputs, can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming.
  6. Functional Programming In computer science, functional programming is a programming

    paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm, which means programming is done with expressions. In functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) each time. Eliminating side effects, i.e. changes in state that do not depend on the function inputs, can make it much easier to understand and predict the behavior of a program, which is one of the key motivations for the development of functional programming.
  7. Reactive Programming In computing, reactive programming is a programming paradigm

    oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow. For example, in an imperative programming setting, a := b + c would mean that a is being assigned the result of b + c in the instant the expression is evaluated. Later, the values of b and c can be changed with no effect on the value of a.
  8. Reactive Programming In computing, reactive programming is a programming paradigm

    oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow. For example, in an imperative programming setting, a := b + c would mean that a is being assigned the result of b + c in the instant the expression is evaluated. Later, the values of b and c can be changed with no effect on the value of a.
  9. Why RxJava? Lesser Cognitive load Code is simpler and much

    more readable Complex operations made easy Operators help do complex tasks like filtering Easy threading Threading in ridiculously simple Easy error handling Error handling is just better Easy to test Unit testing your apps is simple
  10. The Basics Source The source that emits items Observer The

    thing that is interested in the items Composition How to compose the stream of items from the source to the observer.
  11. Source - Observable vs Flowable - Zero or more items

    to be emitted - Can finish successfully or with an error - May not even finish Observable<T> Flowable<T>
  12. Observable variants These are the variants of Observable. None of

    these have backpressure support. Single<T> Completable<T> Maybe<T>
  13. Observer or Subscriber An observer or subscriber consumes the items/stream.

    Example: - Parses the data (more on this later) - Updates UI Subscriber<String> mySubscriber = new Subscriber<String>() { @Override public void onNext(String s) { System.out.println(s); } @Override public void onComplete() { } @Override public void onError(Throwable e) { } @Override public void onSubscribe(Subscription e) { } };
  14. Creating Observables - Observable.create - Observable.just - Observable.from - More

    at https://github.com/ReactiveX/R xJava/wiki/Creating-Observable s Observable<String> myObservable = Observable.just("Hello, world!"); Observable.from("url1", "url2", "url3") .subscribe(url -> System.out.println(url));
  15. Overview - Creation - Subscription - Error handling Observable.just("hello").subscribe(new Observer<String>()

    { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String value) { } @Override public void onError(Throwable e) { } @Override public void onComplete() { } });
  16. Lambda Makes the code much more readable return networkResponseObservable.map(new Func1<NetworkResponse,

    List<Result>>() { @Override public List<Result> call(NetworkResponse networkResponse) { return networkResponse.getResults(); } });
  17. Lambda/Retrolamb da Makes the code much more readable return networkResponseObservable.map(networkResponse

    -> networkResponse.getResults()); return networkResponseObservable.map(new Func1<NetworkResponse, List<Result>>() { @Override public List<Result> call(NetworkResponse networkResponse) { return networkResponse.getResults(); } });
  18. Map - transforms one emitted item into another - http://reactivex.io/docum

    entation/operators/map. html Observable.just("Hello") .map(s -> s + ", world!") .subscribeWith(s -> System.out.println(s));
  19. Zip - combine sets of items emitted by two or

    more Observables together via a specified function and emit items based on the results of this function - http://reactivex.io/docum entation/operators/zip.ht ml /** * {@code Observable} that represents the file with the given driveId, to do that * - We create an {@code Observable} for the title * - We create an {@code Observable} for the {@code DriveContent} * - We zip the above {@code Observable} to create a final {@code File} observable * * @param {@code GoogleApiClient} the {@code GoogleApiClient} which has to do the lookup * @param driveId id of the {@code File} * @return {@code Observable} of the {@code File} with the relevant driveId */ public static Observable<File> downloadFile(final GoogleApiClient googleApiClient, DriveId driveId) { return Observable.zip(getTitleObservable(googleApiClient, driveId), getDriveContentsObservable(googleApiClient, driveId), (title, driveContents) -> { File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), title); FileUtils.copyInputStreamToFile(driveContents.getInputStream(), file); return file; }); }
  20. Other operators - combineLatest - merge - timeout - first,

    last - https://github.com/ReactiveX/RxJava/wiki/Alphabetical-List-of-Observabl e-Operators
  21. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  22. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  23. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  24. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  25. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  26. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  27. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  28. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  29. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  30. Example Observable.zip( MusicApi.getApi().getMusicObservable("Metallica").map(networkResponseMap -> networkResponseMap.getResults()) , MusicApi.getApi().getMusicObservable("IronMaiden").map(networkResponseIM -> networkResponseIM.getResults()) ,

    (results1, results2) -> addAll(results1, results2)) .map(results -> sort(results)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(finalResults -> handleResults(finalResults) ,throwable -> handleThrowable(throwable));
  31. Retrofit - Native support for RxJava - Can return Observables

    instead of Callbacks/Synchronous methods @GET("/info/{id}") Observable<InfoResponse> getInfo(@Path("id") String id);