Slide 1

Slide 1 text

`Rxify` Presented By : Garima Jain @ragdroid A simple spell for complex RxJava operators

Slide 2

Slide 2 text

Who?

Slide 3

Slide 3 text

`Rxify` is for? • Already working on RxJava - More to learn.

Slide 4

Slide 4 text

`Rxify` is for? • Already working on RxJava - More to learn. • Beginner - Time to start Rxifying your apps

Slide 5

Slide 5 text

`Rxify` is for? • Already working on RxJava - More to learn. • Beginner - Time to start Rxifying your apps • Pros - Talk will be fun!

Slide 6

Slide 6 text

What?

Slide 7

Slide 7 text

• `Rxify` - term signifies use of RxJava • RxJava makes our lives simpler. • Cast a spell (use an operator) and we are good to go. `Rxify`

Slide 8

Slide 8 text

• Reactive Extensions for JVM (Java Virtual Machine). • Observer pattern for sequences of data / events. RxJava

Slide 9

Slide 9 text

RxJava makes lives simpler • Never having to worry about : • Low-level Threading • Synchronisation • Background Processing

Slide 10

Slide 10 text

Why?

Slide 11

Slide 11 text

RxJava operators at first glance

Slide 12

Slide 12 text

RxJava operators at first glance

Slide 13

Slide 13 text

RxJava operators at first glance • Complex • Hard to understand • Marble Diagrams? What!!

Slide 14

Slide 14 text

`Rxify` your apps!

Slide 15

Slide 15 text

Basics

Slide 16

Slide 16 text

• Observable produces items, • Subscriber consumes those items. • Observable calls : (Actions) • onNext() multiple times • followed by onComplete() • OR onError() Basics

Slide 17

Slide 17 text

• Operators : • manipulate items between producer and consumer. • Schedulers • Main Thread • Computation (Background Thread) • Test Scheduler Basics

Slide 18

Slide 18 text

Observable Pattern Producer Consumer A B C items Observable emits Subscriber consumes

Slide 19

Slide 19 text

Just-ify Simple Observable String Hello World! Observable.just("Hello World!”); Observable time Hello World

Slide 20

Slide 20 text

A B C A B C Rx-ify String Array Simple Observable Observable.from(new String[] { "A", "B", “C"}); Observable

Slide 21

Slide 21 text

“Spells” operators

Slide 22

Slide 22 text

“Map-io” map() operator

Slide 23

Slide 23 text

Map Transforms every element of a collection of items.

Slide 24

Slide 24 text

Map “Transform the items emitted by an Observable by applying a function to each item” - source Transforms every element of a collection of items.

Slide 25

Slide 25 text

Map-io Observable Map Observable 1 2 3 10 20 30

Slide 26

Slide 26 text

Observable Map Observable.from(new Integer[] { 1, 2, 3})
 .map(new Func1() {
 @Override
 public Integer call(Integer integer) {
 return integer * 10;
 }
 }); Observable 1 2 3 10 20 30

Slide 27

Slide 27 text

Observable Map Observable 1 2 3 10 20 30 via-Hedwig In RxJava 2 Func1 has become Function Func2 has become BiFunction

Slide 28

Slide 28 text

Observable Map Observable.from(new Integer[] { 1, 2, 3})
 .map(new Function() {
 @Override
 public Integer apply(Integer integer) {
 return integer * 10;
 }
 }); Observable 1 2 3 10 20 30

Slide 29

Slide 29 text

“FlatMap-ium” flatMap() operator

Slide 30

Slide 30 text

FlatMap Transforms every element of a collection into another collection of items and combines them into a single collection.

Slide 31

Slide 31 text

FlatMap “Transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable” - source Transforms every element of a collection into another collection of items and combines them into a single collection.

Slide 32

Slide 32 text

FlatMap-ium Observable FlatMap Observable Hello World How Are You? Hello World How Are You?

Slide 33

Slide 33 text

Observable FlatMap Observable.from(new String[] {"Hello World", "How Are You"})
 .flatMap(new Function>() {
 @Override
 public Observable apply(String s) {
 return Observable.from(s.split(" "));
 }
 }); Observable Hello World How Are You? Hello World How Are You?

Slide 34

Slide 34 text

“Filter-rum” filter() operator

Slide 35

Slide 35 text

Filter Filter the original collection to emit items that satisfy a condition.

Slide 36

Slide 36 text

Filter “Emit only those items from an Observable that pass a predicate test" - source Filter the original collection to emit items that satisfy a condition.

Slide 37

Slide 37 text

Filter-rum Observable Filter Observable 1 2 3 1 4 5 6 3 5 7 7

Slide 38

Slide 38 text

Observable Filter Observable 1 2 3 1 4 5 6 3 5 getSourceObservable().filter(new Function() {
 @Override
 public Boolean apply(Integer integer) {
 return integer % 2 == 1;
 }
 }); 7 7

Slide 39

Slide 39 text

“Comples spells” complex operators

Slide 40

Slide 40 text

“Zip-pyosa” zip() operator

Slide 41

Slide 41 text

Zip Combine multiple collections together according to some function and emit the result of each combination.

Slide 42

Slide 42 text

Zip Combine multiple collections together according to some function and emit the result of each combination. “Combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function" - source

Slide 43

Slide 43 text

Zip Marble Diagram

Slide 44

Slide 44 text

Zip Marble Diagram Looks a little Overwhelming

Slide 45

Slide 45 text

Zip Marble Diagram Looks a little Overwhelming

Slide 46

Slide 46 text

Fictional Problem (Polyjuice Potion) • Hermione wants to prepare Polyjuice potion (P = R + H). * • She is waiting for task Ron (R) to bring FluxWeed. • She is waiting for task Harry (H) to bring hair. • Both tasks R and H are executing asynchronously. • Only after both R and H are completed then P can start. * ‘+’ is some complex function (brewing the Polyjuice in this case)

Slide 47

Slide 47 text

Zip-Yosa Observable Zip Observable FluxWeed CrabHair Polyjuice Potion Observable

Slide 48

Slide 48 text

Observable Zip Observable FluxWeed CrabHair Polyjuice Potion Observable 
 return Observable.zip(fluxWeedObservable, hairObservable,
 new BiFunction() {
 @Override
 public PolyJuice apply(final FluxWeed fluxWeed,
 final CrabHair crabHair) {
 return new PolyJuice(fluxWeed, crabHair)
 .prepare();
 }
 });

Slide 49

Slide 49 text

Can you relate the Polyjuice Potion Problem to any coding problem?

Slide 50

Slide 50 text

Can you relate the Polyjuice Portion Problem to any coding problem? YES! When multiple API calls are executing simultaneously.

Slide 51

Slide 51 text

“Concat-ify” concat() operator “Merge-os” merge() operator VS

Slide 52

Slide 52 text

Concat “Emit the emissions from two or more Observables without interleaving them” source “Combine multiple Observables into one by merging their emissions” source Merge

Slide 53

Slide 53 text

Concat Merge 1 2 3 4 8 9 1 2 3 4 8 9 1 2 3 4 8 9 1 2 3 4 8 9 Concat-ify Merge-os

Slide 54

Slide 54 text

Fictional Problem (Snape’s Assignment) • Professor Snape has requested all students to write an essay on werewolves. • The students who will turn in the essay first will get more points than the ones submitting later. • Students are divided into four house observables : • GryffindorObservable (G), • SlytherinObservable (S), • HufflepuffObservable (H) and • RavenclawObservable(R)).

Slide 55

Slide 55 text

Observable Snape’s Assignment - Submission R1 R2 H1 H2 Observable Observable G1 G2 S1 S2 Observable

Slide 56

Slide 56 text

Observable concatify() {
 Observable slytherinObservable = getObservable(House.SLYTHERIN);
 Observable huffleObervable = getObservable(House.HUFFLEPUFF);
 Observable ravenObservable = getObservable(House.RAVENCLAW);
 Observable gryffindorObservable = getObservable(House.GRYFFINDOR);
 return Observable.concat(
 slytherinObservable,
 huffleObervable,
 ravenObservable,
 gryffindorObservable);
 } Snape’s Assignment - Draco’s trick

Slide 57

Slide 57 text

Snape’s Assignment - Draco’s trick S1 S2 H1 H2 R1 R2 G1 G2 Concat-ify Observable R1 R2 H1 H2 Observable Observable G1 G2 S1 S2 Observable

Slide 58

Slide 58 text

Guess who is not so pleased?

Slide 59

Slide 59 text

Guess who is not so pleased? YES!

Slide 60

Slide 60 text

Guess who is not so pleased? YES! Poor Hermione

Slide 61

Slide 61 text

Observable mergeos() {
 Observable slytherinObservable = getObservable(House.SLYTHERIN);
 Observable huffleObervable = getObservable(House.HUFFLEPUFF);
 Observable ravenObservable = getObservable(House.RAVENCLAW);
 Observable gryffindorObservable = getObservable(House.GRYFFINDOR);
 return Observable.merge(
 slytherinObservable,
 huffleObervable,
 ravenObservable,
 gryffindorObservable);
 } Snape’s Assignment - Hermione’s fix

Slide 62

Slide 62 text

Snape’s Assignment - Hermione’s fix G1 S1 G2 R1 H1 S2 R2 H2 Merge-os Observable R1 R2 H1 H2 Observable Observable G1 G2 S1 S2 Observable

Slide 63

Slide 63 text

• Hit the cache first • If data found return data • Else Network call Problem : Cache First Then Network

Slide 64

Slide 64 text

• Hit the cache first • If data found return data • Else Network call Problem : Cache First Then Network Concat-ify

Slide 65

Slide 65 text

• Hit the cache first • If data found return data • Else Network call Observable> cacheObservable = getLecturesFromCache();
 Observable> lecturesFromServer = getLecturesFromServer();
 return cacheObservable .concatWith(lecturesFromServer)
 .take(1); Problem : Cache First Then Network

Slide 66

Slide 66 text

Problem : Cache First Then Network • Hit the cache first • If data found return data • Else Network call Observable> cacheObservable = getLecturesFromCache();
 Observable> lecturesFromServer = getLecturesFromCache();
 return cacheObservable .concatWith(lecturesFromServer)
 .take(1); via-Hedwig when no data, first() : NoSuchElementException : no data take(1) will complete without exception

Slide 67

Slide 67 text

Backpressure “Defence Against the Dark Arts”

Slide 68

Slide 68 text

Backpressure Frequency of Producer producing an item is more than the ability of Consumer to consume.

Slide 69

Slide 69 text

Backpressure Frequency of Producer producing an item is more than the ability of Consumer to consume. “Strategies for coping with Observables that produce items more rapidly than their observers consume them” - source

Slide 70

Slide 70 text

Backpressure via-Hedwig GOOD NEWS!

Slide 71

Slide 71 text

Backpressure via-Hedwig Usually you do not have to worry about back pressure in your applications.

Slide 72

Slide 72 text

Backpressure via-Hedwig RxJava 2 introduces Flowable which is an Observable with backpressure support.

Slide 73

Slide 73 text

Backpressure via-Hedwig With RxJava2, Observables do not support backpressure while Flowables do.

Slide 74

Slide 74 text

Fictional Problem (The Battle) • Dumbledore’s army (Harry, Hermione, Ron and others) • Death Eaters (Lucius Malfoy, Bellatrix Lestrange and others) • Each team is casting lethal spells against the other team. • Dumbledore’s army is not as experienced as the Death Eaters. • Spells produced by Death Eaters is overwhelming the Dumbledore’s army (consumer).

Slide 75

Slide 75 text

“Buffer-undum” buffer() operator

Slide 76

Slide 76 text

Buffer Buffer small chunks of items and emit them instead of emitting one item at a time.

Slide 77

Slide 77 text

Buffer Buffer small chunks of items and emit them instead of emitting one item at a time. “Periodically gather items emitted by an Observable into bundles and emit these bundles rather than emitting the items one at a time" - source

Slide 78

Slide 78 text

Buffer-undum Buffer Observable 1 2 3 4 Observable 1 2 3 4

Slide 79

Slide 79 text

Observable Buffer Observable 1 2 3 4 1 2 getSpellsObservable()
 .buffer(2); //count 3 4

Slide 80

Slide 80 text

Buffer-undum Buffer LOSS-LESS Observable 1 2 3 4 Observable 1 2 3 4

Slide 81

Slide 81 text

Buffer Observable 1 2 3 4 Observable 1 2 3 4

Slide 82

Slide 82 text

“Debounce-y” debounce() operator

Slide 83

Slide 83 text

Debounce From a list of items emit an item only when, some time has passed since it last emitted anything.

Slide 84

Slide 84 text

Debounce From a list of items emit an item only when, some time has passed since it last emitted anything. “Only emit an item from an Observable if a particular timespan has passed without it emitting another item" - source

Slide 85

Slide 85 text

Debounce-y Debounce Observable 1 2 3 4 Observable 1 2 4

Slide 86

Slide 86 text

Observable 1 2 3 4 Observable 1 2 4 getSpellsObservable()
 .debounce(300, TimeUnit.MILLISECONDS); Debounce

Slide 87

Slide 87 text

Observable 1 2 3 4 Observable 1 2 4 Debounce

Slide 88

Slide 88 text

Observable 1 2 3 4 Observable 1 2 4 LOSSY Debounce

Slide 89

Slide 89 text

Observable 1 2 3 4 Observable 1 2 4 PROBLEM SOLVED Debounce

Slide 90

Slide 90 text

Problem : Optimize Network Traffic Track User Events using any analytics library.

Slide 91

Slide 91 text

Problem : Optimize Network Traffic Track User Events using any analytics library. Simple Approach Server request whenever an event occurs. Over chatty producer (User Events) Slow Consumer (Network Request)

Slide 92

Slide 92 text

Problem : Optimize Network Traffic Track User Events using any analytics library. Simple Approach Server request whenever an event occurs. Over chatty producer (User Events) Slow Consumer (Network Request) Backpressure Handling Required

Slide 93

Slide 93 text

Problem : Optimize Network Traffic Track User Events using any analytics library. Buffer-undum Buffer some events before making a network request. Buffer-undum

Slide 94

Slide 94 text

Problem : Optimize Network Traffic Track User Events using any analytics library. Buffer-undum getUserEventsObservable()
 .buffer(3) //buffer count
 .flatMap(new Function, Observable>() {
 @Override
 public Observable apply(final List events) {
 return Observable.just(new TrackRequest(events));
 }
 });

Slide 95

Slide 95 text

Problem : Auto-Search AutoComplete Search Suggestions

Slide 96

Slide 96 text

Problem : Auto-Search AutoComplete Search Suggestions Simple Approach Server request whenever a character is typed Over chatty producer (User Input) Slow Consumer (Network Request)

Slide 97

Slide 97 text

Problem : Auto-Search AutoComplete Search Suggestions Simple Approach Server request whenever a character is typed Over chatty producer (User Input) Slow Consumer (Network Request) Backpressure Handling Required

Slide 98

Slide 98 text

AutoComplete Search Suggestions Debounce-y Make a network request only if user has stopped typing. Debounce-y Solution : Auto-Search

Slide 99

Slide 99 text

AutoComplete Search Suggestions Debounce-y getSearchTermObservable()
 .debounce(500, TimeUnit.MILLISECONDS)
 .flatMap(new Function>() {
 @Override
 public Observable apply(String term) {
 return Observable.just(new SearchRequest(term));
 }
 }); Solution : Auto-Search

Slide 100

Slide 100 text

Error Handling “Muggle Art”

Slide 101

Slide 101 text

“Repeat-ium” repeat() operator

Slide 102

Slide 102 text

Repeat Emit the same item multiple times

Slide 103

Slide 103 text

Repeat “Create an Observable that emits a particular item multiple times” - source Emit the same item multiple times

Slide 104

Slide 104 text

Repeat-ium Observable Repeat Observable 1 1 1 1 1 4

Slide 105

Slide 105 text

“Retry-ikulus” retry() operator

Slide 106

Slide 106 text

Retry On error, retry the same task until successfully completed.

Slide 107

Slide 107 text

Retry “If a source Observable emits an error, resubscribe to it in the hopes that it will complete without error” - source On error, retry the same task until successfully completed.

Slide 108

Slide 108 text

Retry Observable 1 Observable 1 2 3 2 x S U B S C R I B E

Slide 109

Slide 109 text

Retry-ikulus Retry Observable 1 Observable 1 2 3 2 x S U B S C R I B E

Slide 110

Slide 110 text

Retry Observable 1 Observable 1 2 3 2 x 1 2 3 1 2 3 S U B S C R I B E S U B S C R I B E

Slide 111

Slide 111 text

via-Hedwig repeat() resubscribes when it receives onCompleted(). retry() resubscribes when it receives onError(). 

Slide 112

Slide 112 text

Fictional Problem (Professor Lupin’s Boggart) Perform a “Riddikulus” charm 1. Successfully 2. Excellently

Slide 113

Slide 113 text

Fictional Problem (Professor Lupin’s Boggart) via-Hedwig “Riddikulus” charm is a magical spell to turn a Boggart  — your worst fear, into something funny Perform a “Riddikulus” charm 1. Successfully 2. Excellently

Slide 114

Slide 114 text

Fictional Problem (Professor Lupin’s Boggart) Perform a “Riddikulus” charm 1. Successfully 2. Excellently SCARY FUNNY HILARIOUS Observable

Slide 115

Slide 115 text

Fictional Problem (Professor Lupin’s Boggart) SCARY FUNNY Successful Observable Laughter Threshold 0 FUNNY_THRESHOLD Perform a “Riddikulus” charm 1. Successfully 2. Excellently

Slide 116

Slide 116 text

Fictional Problem (Professor Lupin’s Boggart) Perform a “Riddikulus” charm 1. Successfully 2. Excellently SCARY FUNNY HILARIOUS Successful Excelled Observable 0 FUNNY_THRESHOLD HILARIOUS_THRESHOLD Laughter Threshold

Slide 117

Slide 117 text

Fictional Problem (Professor Lupin’s Boggart) via-Hedwig “Something is funny when it makes you laugh, but it becomes hilarious when it is extremely funny” . Perform a “Riddikulus” charm 1. Successfully 2. Excellently

Slide 118

Slide 118 text

Fictional Problem (Professor Lupin’s Boggart) • Boggart has 3 states : SCARY, FUNNY and HILARIOUS. • Riddikulus Charm on Boggart, it’s state : Remain same (if it doesn’t cross the FUNNY_THRESHOLD), OR Change to FUNNY (if it crosses FUNNY_THRESHOLD) OR Change to HILARIOUS (if it crosses HILARIOUS_THRESHOLD). • We need to retry until the Boggart is atleast FUNNY. • We need to repeat until the Boggart becomes HILARIOUS.

Slide 119

Slide 119 text

Solution SCARY SCARY S U B S C R I B E x Retry-kulus SCARY FUNNY S U B S C R I B E SCARY Repeat-ium HILARIOUS

Slide 120

Slide 120 text

Solution getBoggartObservable()
 .flatMap(new Function>() {
 @Override
 public Observable apply(Boggart boggart) {
 boggart.init();
 boggart.riddikulus();
 if (boggart.isFunny()) {
 return Observable.just(boggart);
 }
 return Observable.error(new BoggartException());
 }
 })
 .retry()
 .repeat(10)
 .takeUntil(new Function() {
 @Override
 public Boolean apply(Boggart boggart) {
 return boggart.isHilarious();
 }
 });

Slide 121

Slide 121 text

Problem : Session Renewal Keep session alive while user is browsing the app.

Slide 122

Slide 122 text

Problem : Session Renewal Keep session alive while user is browsing the app. Simple Approach Checking for session validity before performing any API call.

Slide 123

Slide 123 text

Problem : Session Renewal Keep session alive while user is browsing the app. Simple Approach Checking for session validity before performing any API call. Drawback Place session.isValid() check before each API call.

Slide 124

Slide 124 text

Problem : Session Renewal Keep session alive while user is browsing the app. Another Approach Renew the token repeatedly while user is browsing the app.

Slide 125

Slide 125 text

Problem : Session Renewal Keep session alive while user is browsing the app. Another Approach Renew the token repeatedly while user is browsing the app. Repeat-ium

Slide 126

Slide 126 text

Solution : Session Renewal Observable sessionObservable = SessionManager.getCurrentSessionObservable()
 .filter(new Function() {
 @Override
 public Boolean apply(Session session) {
 return session.isValid();
 }
 });

Slide 127

Slide 127 text

Solution : Session Renewal Observable sessionObservable = SessionManager.getCurrentSessionObservable()
 .filter(new Function() {
 @Override
 public Boolean call(Session session) {
 return session.isValid();
 }
 }); Observable renewSessionObservable =
 SessionManager.getCurrentSessionObservable()
 .flatMap(new Function>() {
 @Override
 public Observable apply(Session session) {
 return authService.renewSession(session.getSessionId())
 .repeatWhen(new Function, Observable>() {
 @Override
 public Observable apply(Observable observable) {
 return observable.delay(Session.EXPIRY_TIME_IN_MILLIS,
 TimeUnit.MILLISECONDS);
 }
 });
 }
 });

Slide 128

Slide 128 text

Solution : Session Renewal Observable sessionObservable = SessionManager.getCurrentSessionObservable()
 .filter(new Function() {
 @Override
 public Boolean apply(Session session) {
 return session.isValid();
 }
 }); Observable renewSessionObservable =
 SessionManager.getCurrentSessionObservable()
 .flatMap(new Function>() {
 @Override
 public Observable apply(Session session) {
 return authService.renewSession(session.getSessionId())
 .repeatWhen(new Function, Observable>() {
 @Override
 public Observable apply(Observable observable) {
 return observable.delay(Session.EXPIRY_TIME_IN_MILLIS,
 TimeUnit.MILLISECONDS);
 }
 });
 }
 }); sessionObservable.concatWith(renewSessionObservable);

Slide 129

Slide 129 text

Demo “Multiple API calls”

Slide 130

Slide 130 text

Coding Problem (Polyjuice Potion) • We are waiting for FluxWeed API call. • We are also waiting for Student API call to get hair of Crab. • Both the calls executing asynchronously. • Problem : • Initialise PolyJuice from the results of API calls. • Hide the loader after both calls have completed.

Slide 131

Slide 131 text

Coding Problem (Polyjuice Potion) • We are waiting for FluxWeed API call. • We are also waiting for Student API call to get hair of Crab. • Both the calls executing asynchronously. • Problem : • Initialise PolyJuice from the results of API calls. • Hide the loader after both calls have completed. Without RxJava : SEMAPHORES!

Slide 132

Slide 132 text

Zip-Yosa Observable Zip Observable FluxWeed CrabHair Polyjuice Potion Observable

Slide 133

Slide 133 text

• Learn by practice • Make RxJava your friend and not a foe • Learn by examples - Kaushik Gopal RxJava https://github.com/kaushikgopal/RxJava-Android-Samples • Learn more about RxJava 2 https://github.com/kaushikgopal/RxJava-Android-Samples • Have a look at the source code of demo app https://github.com/ragdroid/rxify • My Medium blogs for more details https://medium.com/@ragdroid What’s Next

Slide 134

Slide 134 text

Acknowledgements via-Hedwig - Vikas @vickyturtle - Julien - Ritesh @_Riteshhh - DroidconIN team

Slide 135

Slide 135 text

Acknowledgements via-Hedwig The terms lossy and lossless have been inspired from the post here.

Slide 136

Slide 136 text

Acknowledgements via-Hedwig repeat() resubscribes when it receives onCompleted(). retry() resubscribes when it receives onError().  — Dan Lew

Slide 137

Slide 137 text

Acknowledgements via-Hedwig “Something is funny when it makes you laugh, but it becomes hilarious when it is extremely funny” — source

Slide 138

Slide 138 text

Acknowledgements via-Hedwig Technical Definitions have been taken from website.

Slide 139

Slide 139 text

Acknowledgements via-Hedwig Fragmented Podcast here

Slide 140

Slide 140 text

Acknowledgements via-Hedwig Gifs have been taken from giphy.com.

Slide 141

Slide 141 text

Thank You

Slide 142

Slide 142 text

FUELED http://fueled.com [email protected] +1.800.962.4587 568 Broadway, 11th Flr. New York, NY 10012 Questions?