reactive programming with rxandroid

31
Introduce RxJava and Android Author: Đới Thanh Thịnh Savvycom-software

Upload: savvycom-savvycom

Post on 16-Jan-2017

72 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Reactive programming with RxAndroid

Introduce RxJava and Android

Author: Đới Thanh ThịnhSavvycom-software

Page 2: Reactive programming with RxAndroid

Introduction1. Developing a complex Android app that has lots of

network connections, user interactions, and animations often means writing code that is full of nested callbacks.

2. Sometimes called callback hell, is not only lengthy and hard to understand, hard to maintain.

3. ReactiveX offers an alternative approach that is both clear and concise, to manage asynchronous tasks and events.

Page 3: Reactive programming with RxAndroid

Overview 1. What is ReactiveX? 2. Observables, Observers 3. Operator 4. Schedulers 5. Retrofit with RxAndroid

Page 4: Reactive programming with RxAndroid

What is ReactiveX? ReactiveX is a library for composing

asynchronous and event-based programs by using observable sequences.

RxJava, which is a port of the Reactive Extensions library from .NET, enables Android apps to be built in this style.

Page 5: Reactive programming with RxAndroid

Async programming Nowadays programming in an imperative single threaded way

usually leads to strange behaviors, blocking non responsive UIs and therefore a bad user experience.

This can be avoided by handling unpredicted things asynchronously. For example actively waiting for a database query or a webservice call can cause an application freeze, if the network is not responsive.

Page 6: Reactive programming with RxAndroid

Async programmingpublic List<Todo> getTodos() {

List<Todo> todosFromWeb = // query a webservice (with bad network latency)

return todosFromDb;}

public void getTodos(Consumer<List<Todo>> todosConsumer) {

Thread thread = new Thread(()-> { List<Todo> todosFromWeb = // query a webservice

todosConsumer.accept(todosFromWeb); }); thread.start();}

Page 7: Reactive programming with RxAndroid

SetupSetup your app/build.gradle:dependencies { compile 'io.reactivex:rxandroid:1.2.0' compile 'io.reactivex:rxjava:1.1.4'}

Page 8: Reactive programming with RxAndroid

Observables, Observers and Subscriptions1. Observables

Emit items (Objects, Strings, Integers etc.). Does not start emitting till someone subscribes.

2. Observers To watch Observables by subscribing to them and consumes data

3. Manipulation operators (this is the “functional programming” part) Transforms Filters Etc.

The observable we just created will emit its data only when it has at least one observer.

Similar to the observer pattern. Except, doesn’t start emitting till there is a subscriber.

Page 9: Reactive programming with RxAndroid

Creating Observable RxJava provides several methods to create an

observable. Observable.just() - Allows to create an observable as

wrapper around other data types Observable.from() - takes a collection or an array and

emits their values in their order in the data structure Observable.fromCallable() - Allows to create an

observable for a Callable` To create observers: Implement Action1 - Allow you to create a simple

observer which has a call methods. This method is called if a new object is emitted.

Page 10: Reactive programming with RxAndroid

Defining Observables// Observables emit any number of items to be processed// The type of the item to be processed needs to be specified as a "generic type"// In this case, the item type is `String`Observable<String> myObservable = Observable.create( new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> sub) { // "Emit" any data to the subscriber sub.onNext("a"); sub.onNext("b"); sub.onNext("c"); // Trigger the completion of the event sub.onCompleted(); } });

This observable event emits the data “a”, “b”, “c” and then completes.

Page 11: Reactive programming with RxAndroid

Defining Observers

Observer<String> mySubscriber = new Observer<String>() { // Triggered for each emitted value @Override public void onNext(String s) { System.out.println("onNext: " + s); }

// Triggered once the observable is complete @Override public void onCompleted() { System.out.println("done!"); }

// Triggered if there is any errors during the event @Override public void onError(Throwable e) { }};

Now let’s create a Observer to consume this emitted data from the Observable:

RxAndroid

Page 12: Reactive programming with RxAndroid

Subscribing to Observables

An Observer can be attached to an Observable in order to respond to emitted data with:

• // Attaches the subscriber above to the observable object• myObservable.subscribe(mySubscriber);Outputs:

// onNext: "a"// onNext: "b"// onNext: "c"// done!

RxAndroid

Observable Observers

Page 13: Reactive programming with RxAndroid

Subscribing to Observables void onNext(T t): Provides the Observer with a new item to observe. may call this method 0 or more times. will not call this method again after it calls either onCompleted or onError void onCompleted(): Notifies the Observer that the Observable has finished sending push-based

notifications. void onError(Throwable e):

Notifies the Observer that the Observable has experienced an error condition.

Subscription subscribe(final Observer<? super T> observer): Subscribes to an Observable and provides an Observer that implements

functions to handle the items the Observable emits and any error or completion

Page 14: Reactive programming with RxAndroid

Operator Just — convert an object or a set of objects into an Observable that emits that or

those objects

Observable.just(1, 2, 3).subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { System.out.println("Complete!"); }

@Override public void onError(Throwable e) {

}

@Override public void onNext(Integer integer) { System.out.println("onNext!"); }});

System.out: onNext!: 1System.out: onNext!: 2System.out: onNext!: 3System.out: Complete!

Page 15: Reactive programming with RxAndroid

Operator From — Converts an Array into an Observable that emits the items in the Array.

Integer[] items = {0, 1, 2, 3, 4};

Observable.from(items).subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { System.out.println("Complete!"); }

@Override public void onError(Throwable e) {

}

@Override public void onNext(Integer integer) { System.out.println("onNext from!" + integer); }});

System.out: onNext!0System.out: onNext!1System.out: onNext!2System.out: onNext!3System.out: onNext!4

System.out: Complete!

Page 16: Reactive programming with RxAndroid

Operator Filter : Filters items emitted by an Observable by only emitting those that

satisfy a specified predicate.Observable.just(1, 2, 3, 4, 5) .filter(new Func1<Integer, Boolean>() { @Override public Boolean call(Integer integer) { return integer < 4; } }).subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { System.out.println("Complete!"); }

@Override public void onError(Throwable e) { System.out.println("onError!"); }

@Override public void onNext(Integer integer) { System.out.println("onNext just!" + integer); }});

System.out: onNext!0System.out: onNext!1System.out: onNext!2System.out: onNext!3

System.out: Complete!

Page 17: Reactive programming with RxAndroid

Operator Map: Transform the items emitted by an Observable by applying a function to each item

Observable.just(1, 2, 3, 4, 5) .map(new Func1<Integer, Integer>() { @Override public Integer call(Integer integer) {

return integer * 10; } }).subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { System.out.println("Complete!"); }

@Override public void onError(Throwable e) { System.out.println("onError!"); }

@Override public void onNext(Integer integer) { System.out.println("onNext!" + integer); }});

System.out: onNext! 10System.out: onNext! 20System.out: onNext! 30System.out: onNext! 40System.out: onNext! 50 System.out: Complete!

Page 18: Reactive programming with RxAndroid

Operator – Many Others http://reactivex.io/documentation/operators.html

Operators By Category Creating Observables: Create, Just … Transforming Observables: Map, FlatMap, … Filtering Observables: First , Filter , … Combining Observables: Join , Merge ,… Error Handling Operators: Catch , Retry Observable Utility Operators:Subscribe, SubscribeOn Conditional and Boolean Operators:Contains, … Mathematical and Aggregate Operators:Average, Count

Page 19: Reactive programming with RxAndroid

Schedulers RxJava is synchronous by default, but work can be defined

asynchronously using schedulers. For instance, we can define that the network call should be done on a background thread, but the callback should be done on the main UI thread.

Observable.from(doLongNetwork())

.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())

.subscribe(getObserver())

1. Observable

2.Schedulers

3. Observer

Page 20: Reactive programming with RxAndroid

Schedulers

These schedulers than then be used to control which thread an observable or the subscriber are operating on using the subscribeOn() and observeOn()

Page 21: Reactive programming with RxAndroid

Schedulers subscribeOn():

Basic rules of rxjava threading:

1. rxjava is single threaded by default 2. subscribeOn only affects upstream3. only the subscribeOn closest to the source matters4. observeOn only affects downstream

Page 22: Reactive programming with RxAndroid

Schedulers1. rxjava is single threaded by defaultWhen you do not use observeOn, subscribeOn, or an operator that runs on a particular scheduler , the callback will be receieved on the thread subscribe happened on.

2. subscribeOn only affects upstreamgetANumberObservable() .subscribeOn(Schedulers.io()) .map(new Func1<Integer, String>() { @Override public String call(Integer integer) { Log.i("Operator thread", Thread.currentThread().getName()); return String.valueOf(integer); } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.i("Subscriber thread", Thread.currentThread().getName() + " onNext: " + s); } });

Output:Observable thread: RxIoScheduler-2Operator thread: RxIoScheduler-2Subscriber thread: RxIoScheduler-2 onNext: 1

Page 23: Reactive programming with RxAndroid

Schedulers3. Only the subscribeOn closest to the source matters:

Observable.just("Some String") .map(new Func1<String, Integer>() { @Override public Integer call(String s) { return s.length(); } }) .subscribeOn(Schedulers.computation()) // changing to computation .subscribeOn(Schedulers.io()) // won’t change the thread to IO .subscribe(new Observer<Integer>() { @Override public void onCompleted() {

}

@Override public void onError(Throwable e) {

}

@Override public void onNext(Integer integer) { System.out.println("onNext!" + integer); Log.d("onNext", "Number " + integer + " Thread: " + Thread.currentThread().getName()); } });

OutputSystem.out: onNext!11 onNext: Number 11 Thread: RxComputationScheduler-1

Page 24: Reactive programming with RxAndroid

Schedulers4. observeOn only affects downstream

ObserveOn function () pass an argument is a Scheduler will make the Operator and Subscriber called behind it is running on thread provided by this Scheduler.

Page 25: Reactive programming with RxAndroid

observeOngetANumberObservable() //.subscribeOn(Schedulers.io()) .observeOn(Schedulers.newThread()) .map(new Func1<Integer, String>() { @Override public String call(Integer integer) { Log.i("Operator thread", Thread.currentThread().getName()); return String.valueOf(integer); } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Log.i("Subscriber thread", Thread.currentThread().getName() + " onNext: " + s); } });

OutputObservable thread: main Operator thread: RxNewThreadScheduler-1Subscriber thread: RxNewThreadScheduler-1 onNext: 1

Page 26: Reactive programming with RxAndroid

Deferring Observable

Create(…): actually creates Observable immediately.

public final static <T> Observable<T> create(OnSubscribe<T> f) { return new Observable<T>(hook.onCreate(f)); }

Defer(…): creates Observable only when subscriber subscribes, create a new Observable each time you get a subscriber.

public final static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) { return create(new OnSubscribeDefer<T>(observableFactory));}

Page 27: Reactive programming with RxAndroid

Deferring ObservableSomeType instance = new SomeType();Observable<String> value = instance.valueObservable();instance.setValue("Some Value");value.subscribe(new Subscriber<String>() { @Override public void onCompleted() {

}

@Override public void onError(Throwable e) {

}

@Override public void onNext(String s) { Log.d("Thinhdt", "Defer Observable: " + s); }});

Output: Thinhdt: Defer Observable: null

Page 28: Reactive programming with RxAndroid

Deferring Observable : Solutionpublic Observable<String> valueObservable() { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext(value); subscriber.onCompleted(); } });}

Observable.create()

public Observable<String> valueObservable() { return Observable.defer(new Func0<Observable<String>>() { @Override public Observable<String> call() { return Observable.just(value); } });}

Observable.defer

Page 29: Reactive programming with RxAndroid

Replacing AsyncTask with Observables// This constructs an `Observable` to download the imagepublic Observable<Bitmap> getImageNetworkCall() { // Insert network call here!}

// Construct the observable and use `subscribeOn` and `observeOn`// This controls which threads are used for processing and observingSubscription subscription = getImageNetworkCall() // Specify the `Scheduler` on which an Observable will operate .subscribeOn(Schedulers.io()) // Specify the `Scheduler` on which a subscriber will observe this `Observable` .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Bitmap>() {

// This replaces `onPostExecute(Bitmap bitmap)` @Override public void onNext(Bitmap bitmap) { // Handle result of network request }

@Override public void onCompleted() { // Update user interface if needed }

@Override public void onError() { // Update user interface to handle error }

});

1. Thread to perform the task in the background used subscribeOn()

2. To update UI on main thread used observeOn()

Page 30: Reactive programming with RxAndroid

Retrofit with RxAndroid1. public interface MyApiEndpointInterface { @GET("/users/{username}") Observable<User> getUser(@Path("username") String username);}

2. MyApiEndpointInterface apiService = retrofit.create(MyApiEndpointInterface.class);

// Get the observable User objectObservable<User> call = apiService.getUser(username);// To define where the work is done, we can use `observeOn()` with Retrofit// This means the result is handed to the subscriber on the main threadcall.observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<User>() { @Override public void onNext(User user) { // Called once the `User` object is available }

@Override public void onCompleted() { // Nothing to do here }

@Override public void onError(Throwable e) { // cast to retrofit.HttpException to get the response code if (e instanceof HttpException) { HttpException response; int code = response.code(); } }});