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

Reactive Extensions : RxJava

Reactive Extensions : RxJava

Mouna Cheikhna

March 09, 2016
Tweet

More Decks by Mouna Cheikhna

Other Decks in Programming

Transcript

  1. API : Observable A simple interface with just Subscribe method.

    Any Observable<T> is a streaming sequence of T objects. So if a method returned an Observable<Price> think of it as a stream of Prices. Observable : a collection of future values.
  2. API : Observable Observable as the push-based, asynchronous equivalent of

    the pull-based, synchronous Iterable. The Observable contract : zero to N data events can happen, followed by a complete event. or an error event can happen at any time, also completing the Observable.
  3. API : Observer Provides a mechanism for receiving push-based notifications.

    After an Observer calls an Observable's subscribe method, the Observable calls the Observer's onNext(T) method to provide notifications. Observable will call an Observer's onCompleted() method exactly once or the Observer's onError(java.lang. Throwable) method exactly once.
  4. API: onNext, onCompleted, and onError The Subscribe method is how

    you connect an observer to an Observable. onNext : An Observable calls this method whenever the Observable emits an item. onError : Indicates failure to generate the expected data or some other error. Stops the Observable and will not make further calls to onNext or onCompleted. onCompleted : Called after onNext for the final time, if it has not encountered any errors.
  5. Example Iterable<String> is = Arrays.asList("a", "b", "c"); ArrayList<String> ts =

    new ArrayList<>(); for(String s : is) { ts.add("new : " + s); } Observable<String> os = Observable.just("a", "b", "c"); os.map(s -> "new : "+ s);
  6. Example // Create our sequence for querying best available data

    Observable<Data> source = Observable.concat( sources.memory(), sources.disk(), sources.network() ) .first(data -> data != null && data.isUpToDate()); // "Request" latest data once a second Observable.interval(1, TimeUnit.SECONDS) .flatMap(__ -> source) .subscribe(data -> System.out.println("Received: " + data.value)); // Occasionally clear memory (as if app restarted) so that we must go to disk Observable.interval(3, TimeUnit.SECONDS) .subscribe(__ -> sources.clearMemory());
  7. Example Observable<Boolean> request(String... permissions) { //… } Observable<Location> getLastKnownLocation() {

    //… } Observable<Location> requestOneLocation() { //.. } requestPermission(Manifest.permission.ACCESS_FINE_LOCATION) .filter(isTrue()) .withLatestFrom(getLastKnownLocation(), (isGranted, location) -> location) .switchIfEmpty(requestOneLocation()) .subscribe(new Subscriber<Location>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(Location location) { Toast.makeText(mContext, "Location : " + location.toString()), Toast.LENGTH_LONG).show(); } });
  8. Error Handling : onErrorReturn Observable.interval(1, TimeUnit.SECONDS) .map(input -> { throw

    new RuntimeException(); }) .onErrorReturn(error -> "Uh oh") .subscribe(System.out::println);
  9. Error Handling : Retry Observable.interval(1, TimeUnit.SECONDS) .map(input -> { if

    (Math.random() < .5) { throw new RuntimeException(); } return "Success " + input; }).retry() .subscribe(System.out::println);
  10. Schedulers: Example Choose to do your work such as invoking

    a subscription, observing or producing notifications, on any thread you like. Control the concurrency model for: 1. The invocation of the subscription 2. The observing of notifications locationService.getLocationsNearby(lon, lat, maxDistance, limit) .map(x -> x.location) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); observable .subscribeOn(Schedulers.newThread()) .unsubscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread());
  11. Subjects Represents an object that is both an Observable and

    an Observer. When to use a subject : A source observable can be one of two kinds: external and local : An external source is any observable or event that already exists outside of your code. A local source is when you generate an observable from your code. 1. If the source is external, then do not use a subject. 2. If the source is local, then do use a subject.
  12. Subjects: BehaviorSubject When an observer subscribes to a BehaviorSubject, it

    begins by emitting the item most recently emitted by the source Observable (or a seed/default value if none has yet been emitted) and then continues to emit any other items emitted later by the source Observable(s).
  13. Subjects: PublishSubject Subject that, once an Observer has subscribed, emits

    all subsequently observed items to the subscriber.
  14. Example public class IntentHolder { private Intent data; private int

    requestCode; int resultCode; } public class MyActivity extends Activity { PublishSubject<IntentHolder> mActivityResultsSubject; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); mActivityResultsSubject.onNext(new IntentHolder(data, requestCode, resultCode)); } } // not a fragment nor an activity class AnotherClass { Observable<IntentHolder> activityResultsEvents; void myMethod() { activityResultsEvents.subscribe(intentHolder -> { onResult(intentHolder.getRequestCode(), intentHolder.getData()); If(intentHolder.getRequestCode() == getRequestCode()) { // do something }}); } }
  15. Plugins Plugins allow you to modify the default behavior of

    RxJava in several respects: • by changing the set of default computation, i/o, and new thread Schedulers • by registering a handler for extraordinary errors that RxJava may encounter • by registering functions that can take note of the occurrence of several regular RxJava activities Examples: • RxJavaSchedulersHook • RxJavaErrorHandler
  16. Testing: TestSubscriber TestSubscriber<String> ts = new TestSubscriber<>(); Observable.interval(200, TimeUnit.MILLISECONDS) .take(5)

    .map(i -> { return i + " value"; }).subscribe(ts); ts.awaitTerminalEvent(); ts.assertNoErrors(); ts.assertReceivedOnNext(Arrays.asList("0 value", "1 value", "2 value", "3 value", "4 value"));
  17. Testing: TestScheduler TestScheduler test = Schedulers.test(); TestSubscriber<String> ts = new

    TestSubscriber<>(); Observable.interval(200, TimeUnit.MILLISECONDS, test) .map(i -> { return i + " value"; }).subscribe(ts); test.advanceTimeBy(200, TimeUnit.MILLISECONDS); ts.assertReceivedOnNext(Arrays.asList("0 value")); test.advanceTimeTo(1000, TimeUnit.MILLISECONDS); ts.assertReceivedOnNext(Arrays.asList("0 value", "1 value”, "2 value", "3 value", "4 value"));