Slide 1

Slide 1 text

5 RXJAVA TIPS YOU MIGHT NOT KNOW HIROSHI KUROKAWA (FABLIC, INC.) POTATOTIPS #29, MAY 25TH, 2016

Slide 2

Slide 2 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription signInSubscription = null; private void sendSignInRequest() { signInSubscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (signInSubscription != null) { signInSubscription.unsubscribe(); } super.onDestroy(); } ▸ In RxJava, it’s really important to call unsubscribe() ▸ If you forgot it, memory leak would occur

Slide 3

Slide 3 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription signInSubscription = null; private void sendSignInRequest() { signInSubscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (signInSubscription != null) { signInSubscription.unsubscribe(); } super.onDestroy(); } ▸ In RxJava, it’s really important to call unsubscribe() ▸ If you forgot it, memory leak would occur

Slide 4

Slide 4 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription subscription = null; private void sendSignInRequest() { subscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (subscription != null) { subscription.unsubscribe(); } super.onDestroy(); }

Slide 5

Slide 5 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription subscription = null; private void sendSignInRequest() { subscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (subscription != null) { subscription.unsubscribe(); } super.onDestroy(); } Use Subscriptions.empty() instead

Slide 6

Slide 6 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription subscription = null; private void sendSignInRequest() { subscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (subscription != null) { subscription.unsubscribe(); } super.onDestroy(); }

Slide 7

Slide 7 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription subscription = private void sendSignInRequest() { subscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (subscription != null) { subscription.unsubscribe(); } super.onDestroy(); }

Slide 8

Slide 8 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription subscription = Subscriptions.empty(); private void sendSignInRequest() { subscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { if (subscription != null) { subscription.unsubscribe(); } super.onDestroy(); }

Slide 9

Slide 9 text

POTATOTIPS #29 (2016-05-25) 1. AVOID NULL CHECK FOR SUBSCRIPTION - SINGLE private Subscription subscription = Subscriptions.empty(); private void sendSignInRequest() { subscription = service.signInUser(new SignInRequest(email, password)) .subscribe(...); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); }

Slide 10

Slide 10 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private Subscription subscription = Susbscriptions.empty(); // can be called multiple times private void update() { // cancel the previous request if necessary if (!subscription.isUnsubscribed()) { subscription.unsubscribe(); } subscription = service.fetchData() .subscribe(...); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); } Awkward

Slide 11

Slide 11 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private Subscription subscription = Susbscriptions.empty(); // can be called multiple times private void update() { // cancel the previous request if necessary if (!subscription.isUnsubscribed()) { subscription.unsubscribe(); } subscription = service.fetchData() .subscribe(...); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); }

Slide 12

Slide 12 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private Subscription subscription = // can be called multiple times private void update() { // cancel the previous request if necessary if (!subscription.isUnsubscribed()) { subscription.unsubscribe(); } subscription = service.fetchData() .subscribe(...); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); }

Slide 13

Slide 13 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private SerialSubscription subscription = new SerialSubscription(); // can be called multiple times private void update() { // cancel the previous request if necessary if (!subscription.isUnsubscribed()) { subscription.unsubscribe(); }. subscription = service.fetchData() .subscribe(...); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); }

Slide 14

Slide 14 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private SerialSubscription subscription = new SerialSubscription(); // can be called multiple times private void update() { // cancel the previous request if necessary subscription = service.fetchData() .subscribe(...); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); }

Slide 15

Slide 15 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private SerialSubscription subscription = new SerialSubscription(); // can be called multiple times private void update() { // cancel the previous request if necessary subscription.set(service.fetchData() .subscribe(...)); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); }

Slide 16

Slide 16 text

POTATOTIPS #29 (2016-05-25) 2. REPLACE AN EXISTING SUBSCRIPTION private SerialSubscription subscription = new SerialSubscription(); // can be called multiple times private void update() { // cancel the previous request if necessary subscription.set(service.fetchData() .subscribe(...)); } @Override public void onDestroy() { subscription.unsubscribe(); super.onDestroy(); } The previous subscription is automatically
 unsubscribed

Slide 17

Slide 17 text

POTATOTIPS #29 (2016-05-25) 3. APPLY A COMMON SET OF OPERATORS WITH COMPOSE() private void update() { // cancel the previous request if necessary subscription = service.fetchData() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...); } Applying the same thread operators
 every time? Use compose()

Slide 18

Slide 18 text

POTATOTIPS #29 (2016-05-25) 3. APPLY A COMMON SET OF OPERATORS WITH COMPOSE() private void update() { // cancel the previous request if necessary subscription = service.fetchData() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...); }

Slide 19

Slide 19 text

POTATOTIPS #29 (2016-05-25) 3. APPLY A COMMON SET OF OPERATORS WITH COMPOSE() private void update() { // cancel the previous request if necessary subscription = service.fetchData() .subscribe(...); } public static Observable.Transformer applySchedulers() { return new Observable.Transformer() { @Override public Observable call(Observable observable) { return observable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }; }

Slide 20

Slide 20 text

POTATOTIPS #29 (2016-05-25) 3. APPLY A COMMON SET OF OPERATORS WITH COMPOSE() private void update() { // cancel the previous request if necessary subscription = service.fetchData() .compose(RxUtil.applySchedulers()) .subscribe(...); } public static Observable.Transformer applySchedulers() { return new Observable.Transformer() { @Override public Observable call(Observable observable) { return observable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }; }

Slide 21

Slide 21 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable.create(subscriber -> { try { subscriber.onNext(doSomething()); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } }); } ▸ Don’t create your OnSubscribe if possible ▸ It’s hard to implement properly
 Observable contract, Backpressure, Subscription handling

Slide 22

Slide 22 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable.create(subscriber -> { try { subscriber.onNext(doSomething()); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } }); }

Slide 23

Slide 23 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable. (subscriber -> { try { subscriber.onNext(doSomething()); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } }); }

Slide 24

Slide 24 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable.fromCallable(subscriber -> { try { subscriber.onNext(doSomething()); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } }); }

Slide 25

Slide 25 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable.fromCallable(() -> { try { subscriber.onNext(doSomething()); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } }); }

Slide 26

Slide 26 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable.fromCallable(() -> doSomething()); }

Slide 27

Slide 27 text

POTATOTIPS #29 (2016-05-25) 4. AVOID A CUSTOM ONSUBSCRIBE public static Observable do() { return Observable.fromCallable(() -> doSomething()); } ▸ Don’t create your OnSubscribe if possible ▸ Use Observable.fromCallable() instead

Slide 28

Slide 28 text

POTATOTIPS #29 (2016-05-25) 5. CONCAT().FIRST() FOR MULTIPLE RESOURCE ACCESS ▸ concat(observable1, observable2, …) ▸ Concatenates the events emit from the observables ▸ Take events from ovservable1 ▸ On completed, take events from observable2 ▸ And so on ▸ first(condition) ▸ Filters the events and returns the first event satisfying the condition ▸ concat().first() ▸ Access the observables one by one and returns the first valid resource

Slide 29

Slide 29 text

POTATOTIPS #29 (2016-05-25) 5. CONCAT().FIRST() FOR MULTIPLE RESOURCE ACCESS // Create our sequence for querying best available data Observable source = Observable.concat( sources.memory(), sources.disk(), sources.network() ) .first(data -> data != null && data.isUpToDate()); from https://github.com/dlew/rxjava-multiple-sources-sample ▸ Check memory/disk/network one by one and return the available data