Slide 1

Slide 1 text

RxJava Siggi Jónsson - [email protected]

Slide 2

Slide 2 text

• RxJava is a Java VM implementation of Reactive Extensions: a library for composing asynchronous and event-based programs by using observable sequences. What is RxJava?

Slide 3

Slide 3 text

• Java: RxJava • JavaScript: RxJS • C#: Rx.NET • C#(Unity): UniRx • Scala: RxScala • Clojure: RxClojure • C++: RxCpp Platforms • Ruby: Rx.rb • Python: RxPY • Groovy: RxGroovy • JRuby: RxJRuby • Kotlin: RxKotlin • Swift: RxSwift • ObjC: ReactiveCocoa*

Slide 4

Slide 4 text

• Java: RxJava • JavaScript: RxJS • C#: Rx.NET • C#(Unity): UniRx • Scala: RxScala • Clojure: RxClojure • C++: RxCpp Platforms • Ruby: Rx.rb • Python: RxPY • Groovy: RxGroovy • JRuby: RxJRuby • Kotlin: RxKotlin • Swift: RxSwift • ObjC: ReactiveCocoa*

Slide 5

Slide 5 text

• An awesome tool to work with asynchronous streams of data What is RxJava?

Slide 6

Slide 6 text

• Button clicks • Text edits • Network requests • Push notifications • …. What are streams?

Slide 7

Slide 7 text

What is not a stream?

Slide 8

Slide 8 text

The Past Life before RxJava

Slide 9

Slide 9 text

Asynchronous Operations • AsyncTasks • Callbacks • Handlers • Threads • Runnables • Executors • EventBus

Slide 10

Slide 10 text

AsyncTask public class SomeTask extends AsyncTask {
 private WeakReference callback; 
 public SomeTask(Callback callback) {
 callback = new WeakReference(callback);
 }
 
 @Override
 protected SomeResult doInBackground(String... params) { try { //do stuff } catch (Exception e) { //oh god, what now? return null?
 }
 return null;
 }
 
 @Override
 protected void onPostExecute(SomeResult result) { if (callback.get() != null) { callback.onResult(result); }
 }
 }

Slide 11

Slide 11 text

Callback Hell button.setOnClickListener(new View.OnClickListener() {
 public void onClick(View v) {
 loadPlayer(playerId, new Callback() {
 public void playerLoaded(Player p1) {
 loadPlayer(p1.bestFriendId, new Callback() {
 public void playerLoaded(Player p2) {
 loadImage(p2.profileUrl, new ImageCallback() {
 public void imageLoaded(Bitmap bitmap) {
 imageView.setImageBitmap(bitmap);
 }
 });
 }
 });
 }
 });
 }
 });

Slide 12

Slide 12 text

• Did the player reach the Top 10 in a topic in the first month after he joined or the first month after the topic was created (which ever is first)? Complexity grows fast

Slide 13

Slide 13 text

RxJava to the rescue

Slide 14

Slide 14 text

• Observable -> produces events • Observer/Subscriber -> receives events • Operators • Schedulers -> Multithreading RxJava Concepts

Slide 15

Slide 15 text

Observable Observable.create(new Observable.OnSubscribe() {
 @Override
 public void call(Subscriber subscriber) {
 try {
 subscriber.onNext("Hello, World!");
 subscriber.onCompleted();
 }
 catch (Exception e) {
 subscriber.onError(e);
 }
 }
 });

Slide 16

Slide 16 text

Observable Observable.create(new Observable.OnSubscribe() {
 @Override
 public void call(Subscriber subscriber) {
 try {
 subscriber.onNext("Hello, World!");
 subscriber.onCompleted();
 }
 catch (Exception e) {
 subscriber.onError(e);
 }
 }
 });

Slide 17

Slide 17 text

Observable Observable.just("Hello, World!");

Slide 18

Slide 18 text

Observer interface Observer { void onNext(T t); 
 void onCompleted();
 void onError(Throwable e);
 }

Slide 19

Slide 19 text

Putting it together Observable.just("Hello, World").subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) {
 System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 20

Slide 20 text

Putting it together Observable.just("Hello, World").subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) {
 System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 21

Slide 21 text

Putting it together Observable.just("Hello, World").subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) {
 System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 22

Slide 22 text

Putting it together Observable.just("Hello, World").subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) {
 System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 23

Slide 23 text

Putting it together Observable.just("Hello, World").subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) {
 System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 24

Slide 24 text

Putting it together Observable.just("Hello, World").subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) { System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 25

Slide 25 text

Putting it together api.getHello().subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) { System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 26

Slide 26 text

Putting it together api.getHello().subscribe(new Observer() {
 @Override
 public void onCompleted() {
 System.out.println("Done!");
 }
 
 @Override
 public void onError(Throwable e) { System.err.println(e.getMessage());
 }
 
 @Override
 public void onNext(String s) {
 System.out.println(s);
 }
 });

Slide 27

Slide 27 text

Operators The Toolbox

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

• Did the player reach the Top 10 in a topic in the first month after he joined or the first month after the topic was created (which ever is first)? Complexity grows fast

Slide 36

Slide 36 text

Easy Observable.zip(
 playerService.getPlayer(“”),
 topicsService.getTopic("”), player, topic -> {
 if (player.created.before(topic.created))
 return player.created;
 else return topic.created;
 }
 ).flatMap(date -> {
 return topicsService.getLeaderboard("”, date);
 }).flatMap(leaderboard -> 
 return Observable.from(leaderboard.top);
 }).exists(player -> {
 return player.id.equals(""); 
 });

Slide 37

Slide 37 text

Easy

Slide 38

Slide 38 text

Schedulers RxAndroid

Slide 39

Slide 39 text

Schedulers

Slide 40

Slide 40 text

Schedulers • Skipping Frames. The application may be doing too much work on its main thread. • CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. • NetworkOnMainThreadException • :(

Slide 41

Slide 41 text

Schedulers playerService.getFollowers() .subscribe(response -> {
 adapter.addAll(response.players);
 });

Slide 42

Slide 42 text

Schedulers playerService.getFollowers() .observeOn(AndroidSchedulers.mainThread()) .subscribe(response -> {
 adapter.addAll(response.players);
 });

Slide 43

Slide 43 text

Schedulers playerService.getFollowers() .observeOn(AndroidSchedulers.mainThread()) .subscribe(response -> {
 adapter.addAll(response.players);
 });

Slide 44

Slide 44 text

QuizUp Gameplay

Slide 45

Slide 45 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 46

Slide 46 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 47

Slide 47 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 48

Slide 48 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 49

Slide 49 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 50

Slide 50 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 51

Slide 51 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 52

Slide 52 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 53

Slide 53 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 54

Slide 54 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 55

Slide 55 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 56

Slide 56 text

QuizUp Round

Slide 57

Slide 57 text

QuizUp Round Observable events = Observable.concat(
 roundStarted(round),
 showQuestion(round, question).delay(ROUND_START_DELAY),
 showAnswers(round, question).delay(showAnswersDelay),
 answerPeriodStart(round).delay(ANSWER_PERIOD_START_DELAY),
 Observable.merge(
 playerAnswer.takeUntil(timer),
 opponentAnswer.takeUntil(timer),
 timer.takeUntil(bothPlayersHaveAnswered)
 ),
 answerPeriodEnd(round),
 playerDidNotAnswer(round, question, playerDidAnswer),
 verifyOpponentIsStillHere(opponentDidAnswer),
 showCorrectAnswer(round, question).delay(SHOW_CORRECT_ANSWER_DELAY),
 Observable.empty().delaySubscription(FINISH_UP_ROUND_DELAY)
 );

Slide 58

Slide 58 text

All Rounds 
 Observable match = Observable.range(1, 7).concatMap(round -> {
 return round(round);
 });


Slide 59

Slide 59 text

All Rounds 
 Observable match = Observable.range(1, 7).concatMap(round -> {
 return round(round);
 });


Slide 60

Slide 60 text

All Rounds 
 Observable match = Observable.range(1, 7).concatMap(round -> {
 return round(round);
 });


Slide 61

Slide 61 text

All Rounds

Slide 62

Slide 62 text

Thank You q.is/jobs