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

Reactive Programming with RxJava

Reactive Programming with RxJava

Introduction to reactive programming concepts based on RxJava library

Yevhen Tsyba

May 23, 2017
Tweet

Other Decks in Programming

Transcript

  1. service.getBadges(userId, new Callback<BadgeResponse>() { @Override public void onSuccess(BadgeResponse badges, Response

    r) { service.getTags(userId, new Callback<TagResponse>() { @Override public void onSuccess(TagResponse tags, Response r) { callback.success( new UserStats(user, tags.getItems(), badges.getItems()), r); } @Override public void failure(Error error) { collback.failure(error); } }); } @Override public void failure(Error error) { collback.failure(error); } })
  2. service.getBadges(userId, new Callback<BadgeResponse>() { @Override public void onSuccess(BadgeResponse badges, Response

    r) { service.getTags(userId, new Callback<TagResponse>() { @Override public void onSuccess(TagResponse tags, Response r) { callback.success( new UserStats(user, tags.getItems(), badges.getItems()), r); } @Override public void failure(Error error) { collback.failure(error); } }); } @Override public void failure(Error error) { collback.failure(error); } })
  3. Observable<Badge> badges = Observable.fromCallable(...); Observable<Tag> tags = Observable.defer(...); Observable<User> users

    = Observable.fromIterable()...); badges .zipWith(tags) .zipWith(users) .map((badge, tag, user) -> new UserStats(user, tags.getItems(), badges.getItems()) ) .subscribeOn(Schedulers.newThread()) .subscribe( next -> this::show);
  4. ExecutorService executor = new ThreadPoolExecutor(4, 4, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());

    try { List<Future<?>> futures = new ArrayList<Future<?>>(); // kick off several async tasks futures.add(executor.submit(new CallToRemoteServiceA())); futures.add(executor.submit(new CallToRemoteServiceB())); futures.add(executor.submit(new CallToRemoteServiceC("A"))); futures.add(executor.submit(new CallToRemoteServiceC("B"))); futures.add(executor.submit(new CallToRemoteServiceC("C"))); futures.add(executor.submit(new CallToRemoteServiceD(1))); futures.add(executor.submit(new CallToRemoteServiceE(2))); futures.add(executor.submit(new CallToRemoteServiceE(3))); futures.add(executor.submit(new CallToRemoteServiceE(4))); futures.add(executor.submit(new CallToRemoteServiceE(5))); // as each completes do further work // keep polling until all work is done while (futures.size() > 0) { // use an iterator so we can remove from it Iterator<Future<?>> i = futures.iterator(); while (i.hasNext()) { Future<?> f = i.next(); if (f.isDone()) { // only do work if the Future is done doMoreWork(f.get()); i.remove(); } // otherwise we continue to the next Future } } } finally { executor.shutdownNow(); }
  5. ExecutorService executor = new ThreadPoolExecutor(4, 4, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());

    try { List<Future<?>> futures = new ArrayList<Future<?>>(); // kick off several async tasks futures.add(executor.submit(new CallToRemoteServiceA())); futures.add(executor.submit(new CallToRemoteServiceB())); futures.add(executor.submit(new CallToRemoteServiceC("A"))); futures.add(executor.submit(new CallToRemoteServiceC("B"))); futures.add(executor.submit(new CallToRemoteServiceC("C"))); futures.add(executor.submit(new CallToRemoteServiceD(1))); futures.add(executor.submit(new CallToRemoteServiceE(2))); futures.add(executor.submit(new CallToRemoteServiceE(3))); futures.add(executor.submit(new CallToRemoteServiceE(4))); futures.add(executor.submit(new CallToRemoteServiceE(5))); // as each completes do further work // keep polling until all work is done while (futures.size() > 0) { // use an iterator so we can remove from it Iterator<Future<?>> i = futures.iterator(); while (i.hasNext()) { Future<?> f = i.next(); if (f.isDone()) { // only do work if the Future is done doMoreWork(f.get()); i.remove(); } // otherwise we continue to the next Future } } } finally { executor.shutdownNow(); }
  6. Why Reactive Programming •Simpler code, making it more readable. •Abstracts

    away from boiler plate code to focus on business logic. •Abstracts away from low-level threading, synchronization, and concurrency issues. •Stream processing implies memory efficient. •The model can be applied almost everywhere to solve almost any kind of problem.
  7. CompletableFuture JDK8 RxJava Observable hot starts eagerly hot/cold lazy cached

    (computes only once) buffer on demand emits exactly one element or exception one element or exception (Single) or many elements
  8. Streams JDK8 RxJava Observable pull-based push-based can be used only

    once can be subscribed to many times Stream#parallel() splits sequence into partitions (Spliterator) do not split data Stream#parallel() by default doesn't allow to specify thread pool to use uses Schedulers
  9. Reactive Streams JDK9 vs RxJava JDK9 RxJava v2.0 java.util.concurrent.Flow.Publisher io.reactivex.Flowable

    io.reactivex.Observable java.util.concurrent.Flow.Subscriber io.reactivex.Observer java.util.concurrent.Flow.Processor io.reactivex.subjects.Subject
  10. io.reactivex.Observable public abstract class Observable<T> implements ObservableSource<T> { // Subscribes

    the given Observer to this ObservableSource instance public final Disposable subscribe(Observer<? super T> observer); } public interface Observer<T> { void onSubscribe(Disposable d); void onNext(T value); void onError(Throwable e); void onComplete(); }
  11. io.reactivex.Observable public abstract class Observable<T> implements ObservableSource<T> { // Subscribes

    the given Observer to this ObservableSource instance void subscribe(Observer<? super T> observer); // factory methods public static <T> Observable<T> just(T item); public static <T> Observable<T> fromIterable(Iterable<? extends T> source); // intermediate operations public final <R> Observable<R> map(Function<? super T, ? extends R> mapper); // debug methods public final Observable<T> doOnError(Consumer<? super Throwable> onError); }
  12. io.reactivex.Flowable public abstract class Flowable<T> implements Publisher<T> { // same

    as Observable public final Flowable<T> onBackpressureBuffer(); public final Flowable<T> onBackpressureDrop(); public final Flowable<T> onBackpressureLatest() }
  13. final Observable<Dataset> fromCache = … final Observable<Dataset> fromDatabase = …

    final Observable<Dataset> fromHttp = … final Observable<Dataset> dataset = fromCache .mergeWith(fromDatabase) .mergeWith(fromHttp) .first(); dataset.subscribe(onNext -> this::show, onError -> this::notify);
  14. final Observable<Dataset> fromCache = … final Observable<Dataset> fromDatabase = …

    final Observable<Dataset> fromHttp = … final Observable<Dataset> dataset = Observable .amb( Arrays.asList( fromCache, fromDatabase, fromHttp)) .first(); dataset.subscribe(onNext -> this::show, onError -> this::notify);
  15. Stream of data : USD, UAH, UAH, UAH, USD, UAH,

    … Observable .interval(1, TimeUnit.SECONDS) .map(time -> getByHttp()) .subscribe(…); Received data : USD, UAH, UAH, UAH, USD, UAH, …
  16. Stream of data : USD, UAH, UAH, UAH, USD, UAH,

    … Observable .interval(1, TimeUnit.SECONDS) .map(time -> getByHttp()) .subscribe(…); Received data : USD, UAH, UAH, UAH, USD, UAH, … Observable .interval(1, TimeUnit.SECONDS) .flatMap(time -> Observable .fromIterable(getByHttp())) .distinctUntilChanged() .subscribe(…); Received data : USD, UAH, USD, UAH, USD, …