Slide 1

Slide 1 text

Managing State with RxJava Jake Wharton

Slide 2

Slide 2 text

Why Reactive? Unless you can model your entire system synchronously...

Slide 3

Slide 3 text

Why Reactive? Unless you can model your entire system synchronously, a single asynchronous source breaks imperative programming.

Slide 4

Slide 4 text

Why Reactive? interface UserManager { User getUser();
 }A

Slide 5

Slide 5 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A

Slide 6

Slide 6 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A UserManager um = new UserManager();

Slide 7

Slide 7 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A UserManager um = new UserManager(); System.out.println(um.getUser());

Slide 8

Slide 8 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe");

Slide 9

Slide 9 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe"); System.out.println(um.getUser());

Slide 10

Slide 10 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); // <-- now async void setAge(int age); // <-- now async
 }A

Slide 11

Slide 11 text

Why Reactive? interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe"); System.out.println(um.getUser());

Slide 12

Slide 12 text

Why Reactive? interface UserManager { User getUser(); void setName(String name, Runnable callback); void setAge(int age, Runnable callback);
 }A

Slide 13

Slide 13 text

Why Reactive? interface UserManager { User getUser(); void setName(String name, Runnable callback);A void setAge(int age, Runnable callback);B
 }A UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe", () -> { System.out.println(um.getUser()); });

Slide 14

Slide 14 text

Why Reactive? interface UserManager { User getUser(); void setName(String name, Listener listener);A void setAge(int age, Listener listener);B interface Listener { void success(User user); void failure(IOException e); }G
 }A

Slide 15

Slide 15 text

Why Reactive? UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe");

Slide 16

Slide 16 text

Why Reactive? UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { System.out.println(um.getUser()); }A @Override public void failure(IOException e) { // TODO show the error... }B });

Slide 17

Slide 17 text

Why Reactive? UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { System.out.println(um.getUser()); }A @Override public void failure(IOException e) { // TODO show the error... }B }); um.setAge(40, new UserManager.Listener() { @Override public void success() { System.out.println(um.getUser()); }C 2@Override public void failure(IOException e) {2 2// TODO show the error...2 }D });2

Slide 18

Slide 18 text

Why Reactive? UserManager um = new UserManager(); System.out.println(um.getUser()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { System.out.println(um.getUser()); um.setAge(40, new UserManager.Listener() { @Override public void success() { System.out.println(um.getUser()); }C 2@Override public void failure(IOException e) {2 2// TODO show the error...2 }D });2 }A @Override public void failure(IOException e) { // TODO show the error... }B });

Slide 19

Slide 19 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { tv.setText(um.getUser().toString()); }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 20

Slide 20 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { tv.setText(um.getUser().toString()); }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 21

Slide 21 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { if (isDestroyed()) { tv.setText(um.getUser().toString()); } }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 22

Slide 22 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { if (isDestroyed()) { tv.setText(um.getUser().toString()); } }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 23

Slide 23 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { if (isDestroyed()) { tv.setText(um.getUser().toString()); }L }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 24

Slide 24 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { runOnUiThread(new Runnable() { @Override public void run() { if (isDestroyed()) { tv.setText(um.getUser().toString()); }L }4 }); }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 25

Slide 25 text

Why Reactive? public final class UserActivity extends Activity { private final UserManager um = new UserManager(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user); TextView tv = (TextView) findViewById(R.id.user_name); tv.setText(um.getUser().toString()); um.setName("Jane Doe", new UserManager.Listener() { @Override public void success() { runOnUiThread(new Runnable() { @Override public void run() { if (isDestroyed()) { tv.setText(um.getUser().toString()); } }4 }); }A @Override public void failure(IOException e) { // TODO show the error... }B }); }Y }Z

Slide 26

Slide 26 text

Why Reactive? GET / 200 OK SELECT * Jane Doe setText onClick

Slide 27

Slide 27 text

Why Reactive? GET / 200 OK SELECT * Jane Doe setText onClick

Slide 28

Slide 28 text

Why Reactive? GET / 200 OK SELECT * Jane Doe setText onClick

Slide 29

Slide 29 text

Why Reactive? GET / 200 OK SELECT * Jane Doe setText onClick

Slide 30

Slide 30 text

Why Reactive? GET / 200 OK SELECT * Jane Doe setText onClick

Slide 31

Slide 31 text

Why Reactive? GET / 200 OK SELECT * Jane Doe setText onClick SELECT * Jane Doe setText UPDATE user Jane Doe setText

Slide 32

Slide 32 text

Why Reactive?

Slide 33

Slide 33 text

Why Reactive? Unless you can model your entire system synchronously, a single asynchronous source breaks imperative programming.

Slide 34

Slide 34 text

Why Reactive?

Slide 35

Slide 35 text

Why Reactive?

Slide 36

Slide 36 text

Why Reactive?

Slide 37

Slide 37 text

Why Reactive?

Slide 38

Slide 38 text

Why Reactive?

Slide 39

Slide 39 text

Why Reactive?

Slide 40

Slide 40 text

interface UserManager { User getUser(); void setName(String name); void setAge(int age);
 }A Being Reactive

Slide 41

Slide 41 text

Being Reactive interface UserManager { Observable getUser(); void setName(String name); void setAge(int age);
 }A

Slide 42

Slide 42 text

Being Reactive interface UserManager { Observable getUser(); Completable setName(String name); Completable setAge(int age);
 }A void void


Slide 43

Slide 43 text

Being Reactive um.getUser()

Slide 44

Slide 44 text

Being Reactive um.getUser() .observeOn(AndroidSchedulers.mainThread())

Slide 45

Slide 45 text

Being Reactive um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } });

Slide 46

Slide 46 text

Being Reactive um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } });2

Slide 47

Slide 47 text

Being Reactive disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } }));2

Slide 48

Slide 48 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose();

Slide 49

Slide 49 text

Being Reactive um.setName("Jane Doe")

Slide 50

Slide 50 text

Being Reactive um.setName("Jane Doe") .subscribeOn(Schedulers.io())

Slide 51

Slide 51 text

Being Reactive um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread())

Slide 52

Slide 52 text

Being Reactive um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { }1 @Override public void onError(Throwable t) { // retry or show }2 });

Slide 53

Slide 53 text

Being Reactive um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 });3

Slide 54

Slide 54 text

Being Reactive disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3

Slide 55

Slide 55 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose(); // button click listener disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3

Slide 56

Slide 56 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose(); // button click listener disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3 Push-based updates

Slide 57

Slide 57 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose(); // button click listener disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3 Push-based updates Declarative threading

Slide 58

Slide 58 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose(); // button click listener disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3 Push-based updates Declarative threading Easy error-handling

Slide 59

Slide 59 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose(); // button click listener disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3 Push-based updates Declarative threading Easy error-handling Specialized callbacks

Slide 60

Slide 60 text

Being Reactive // onCreate disposables.add(um.getUser() .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableObserver() { @Override public void onNext(User user) { tv.setText(user.toString()); }1 @Override public void onComplete() { /* ignored */ } @Override public void onError(Throwable t) { /* crash or show */ } })); // onDestroy disposables.dispose(); // button click listener disposables.add(um.setName("Jane Doe") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeWith(new DisposableCompletableObserver() { @Override public void onComplete() { // success! re-enable editing }1 @Override public void onError(Throwable t) { // retry or show }2 }));3 Push-based updates Declarative threading Easy error-handling Specialized callbacks Lifecycle cancelation

Slide 61

Slide 61 text

Managing State Enter name: SUBMIT

Slide 62

Slide 62 text

Managing State Enter name: SUBMIT Jane Doe

Slide 63

Slide 63 text

Managing State Enter name: SUBMIT Jane Doe

Slide 64

Slide 64 text

Managing State Enter name: SUBMIT

Slide 65

Slide 65 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 66

Slide 66 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 67

Slide 67 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 68

Slide 68 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 69

Slide 69 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 70

Slide 70 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 71

Slide 71 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 72

Slide 72 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 73

Slide 73 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 74

Slide 74 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 75

Slide 75 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 76

Slide 76 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 77

Slide 77 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 78

Slide 78 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 79

Slide 79 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 80

Slide 80 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 81

Slide 81 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 82

Slide 82 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 83

Slide 83 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 84

Slide 84 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 85

Slide 85 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 86

Slide 86 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 87

Slide 87 text

Managing State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 88

Slide 88 text

Managing State

Slide 89

Slide 89 text

Managing State RxView.clicks(…)

Slide 90

Slide 90 text

Managing State doOnNext(…)

Slide 91

Slide 91 text

Managing State getText()

Slide 92

Slide 92 text

Managing State flatMap(…)

Slide 93

Slide 93 text

Managing State flatMap(…)

Slide 94

Slide 94 text

Managing State doOnNext(…)

Slide 95

Slide 95 text

Managing State subscribe(…)

Slide 96

Slide 96 text

Managing State

Slide 97

Slide 97 text

Managing State

Slide 98

Slide 98 text

Managing State

Slide 99

Slide 99 text

Managing State RxView.clicks(…)

Slide 100

Slide 100 text

Managing State doOnNext(…)

Slide 101

Slide 101 text

Managing State doOnNext(…) doOnNext(…)

Slide 102

Slide 102 text

Managing State doOnNext(…) doOnNext(…)

Slide 103

Slide 103 text

Managing State getText()

Slide 104

Slide 104 text

Managing State flatMap(…)

Slide 105

Slide 105 text

Managing State doOnNext(…)

Slide 106

Slide 106 text

Managing State subscribe(…)

Slide 107

Slide 107 text

Managing State

Slide 108

Slide 108 text

Managing State

Slide 109

Slide 109 text

Managing State

Slide 110

Slide 110 text

Managing State RxView.clicks(…) getText()

Slide 111

Slide 111 text

Managing State RxView.clicks(…) getText() Observable

Slide 112

Slide 112 text

Managing State doOnNext(…) doOnNext(…) subscribe(…)

Slide 113

Slide 113 text

Managing State doOnNext(…) doOnNext(…) doOnNext(…)

Slide 114

Slide 114 text

Managing State doOnNext(…) doOnNext(…) doOnNext(…)

Slide 115

Slide 115 text

Managing State doOnNext(…) doOnNext(…) subscribe(…)

Slide 116

Slide 116 text

Managing State doOnNext(…) doOnNext(…) subscribe(…)

Slide 117

Slide 117 text

Managing State subscribe(ignored -> …)

Slide 118

Slide 118 text

Managing State subscribe((SubmitUiModel model) -> …) ignored

Slide 119

Slide 119 text

Managing State

Slide 120

Slide 120 text

Managing State

Slide 121

Slide 121 text

Reactive State

Slide 122

Slide 122 text

Reactive State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString())) .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 123

Slide 123 text

Reactive State disposables.add(RxView.clicks(submitView) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(ignored -> service.setName(nameView.getText().toString()))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 124

Slide 124 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> nameView.getText().toString())Y .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(name -> service.setName(name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 125

Slide 125 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString()))Y .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); })); name

Slide 126

Slide 126 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString()))Y .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 127

Slide 127 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString()))Y .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 128

Slide 128 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString()))Y .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 129

Slide 129 text

Reactive State final class SubmitUiModel { final boolean inProgress; final boolean success; final String errorMessage; private SubmitUiModel( boolean inProgress, boolean success, String errorMessage) { // ... } static SubmitUiModel inProgress() { /* ... */ } static SubmitUiModel success() { /* ... */ } static SubmitUiModel failure(String errorMessage) { /* ... */ } }

Slide 130

Slide 130 text

Reactive State final class SubmitUiModel { final boolean inProgress; final boolean success; final String errorMessage; private SubmitUiModel( boolean inProgress, boolean success, String errorMessage) { // ... } static SubmitUiModel inProgress() { /* ... */ } static SubmitUiModel success() { /* ... */ } static SubmitUiModel failure(String errorMessage) { /* ... */ } }

Slide 131

Slide 131 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 132

Slide 132 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .doOnNext(ignored -> { submitView.setEnabled(false); progressView.setVisibility(VISIBLE); }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 133

Slide 133 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .doOnNext(ignored -> { SubmitUiModel.inProgress() }) .flatMap(event -> service.setName(event.name))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); })); .startWith( submitView.setEnabled(false); progressView.setVisibility(VISIBLE);

Slide 134

Slide 134 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .startWith(SubmitUiModel.inProgress()))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 135

Slide 135 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .startWith(SubmitUiModel.inProgress()))X .observeOn(AndroidSchedulers.mainThread()) .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 136

Slide 136 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 137

Slide 137 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 138

Slide 138 text

Reactive State final class SubmitUiModel { final boolean inProgress; final boolean success; final String errorMessage; private SubmitUiModel( boolean inProgress, boolean success, String errorMessage) { // ... } static SubmitUiModel inProgress() { /* ... */ } static SubmitUiModel success() { /* ... */ } static SubmitUiModel failure(String errorMessage) { /* ... */ } }

Slide 139

Slide 139 text

Reactive State final class SubmitUiModel { final boolean inProgress; final boolean success; final String errorMessage; private SubmitUiModel( boolean inProgress, boolean success, String errorMessage) { // ... } static SubmitUiModel inProgress() { /* ... */ } static SubmitUiModel success() { /* ... */ } static SubmitUiModel failure(String errorMessage) { /* ... */ } }

Slide 140

Slide 140 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .doOnNext(ignored -> progressView.setVisibility(GONE)) .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); }));

Slide 141

Slide 141 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(s -> finish(), t -> { submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + t.getMessage(), LENGTH_SHORT).show(); })); progressView.setVisibility(GONE) .doOnNext(ignored -> )

Slide 142

Slide 142 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(s -> finish(), t -> {})); submitView.setEnabled(true); Toast.makeText(this, "Failed to set name: " + , LENGTH_SHORT).show();

Slide 143

Slide 143 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(s -> finish(), t -> {}));

Slide 144

Slide 144 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(s -> finish(), t -> {}));

Slide 145

Slide 145 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); } }, t -> {})); s

Slide 146

Slide 146 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> {}));

Slide 147

Slide 147 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()))X .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 148

Slide 148 text

Reactive State disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())) .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())) .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 149

Slide 149 text

Reactive State Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); disposables.add(events.flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())) .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 150

Slide 150 text

Reactive State Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); Observable models = events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(models.subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 151

Slide 151 text

Reactive State Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); })); models models

Slide 152

Slide 152 text

Reactive State Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 153

Slide 153 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); .compose(submit) .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.errorMessage, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 154

Slide 154 text

Reactive State

Slide 155

Slide 155 text

Reactive State

Slide 156

Slide 156 text

Reactive State

Slide 157

Slide 157 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); .compose(submit) .subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 158

Slide 158 text

Reactive State Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 159

Slide 159 text

Reactive State Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 160

Slide 160 text

Reactive State class SubmitEventZ{ /* ... */ } Observable events = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage()) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 161

Slide 161 text

Reactive State abstract class SubmitUiEvent {} class SubmitEventZextends SubmitUiEventY{ /* ... */ } class CheckNameEvent extends SubmitUiEvent { /* ... */ } Observable submitEvents = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); e

Slide 162

Slide 162 text

Reactive State abstract class SubmitUiEvent {} class SubmitEventZextends SubmitUiEventY{ /* ... */ } class CheckNameEvent extends SubmitUiEvent { /* ... */ } Observable submitEvents = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); Observable checkNameEvents = RxTextView.afterTextChanges(nameView) .map(text -> new CheckNameEvent(text));

Slide 163

Slide 163 text

Reactive State abstract class SubmitUiEvent {} class SubmitEventZextends SubmitUiEventY{ /* ... */ } class CheckNameEvent extends SubmitUiEvent { /* ... */ } Observable submitEvents = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); Observable checkNameEvents = RxTextView.afterTextChanges(nameView) .map(text -> new CheckNameEvent(text)); Observable events = Observable.merge(submitEvents, checkNameEvents);

Slide 164

Slide 164 text

Reactive State Observable events = /* ... */; ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); })); abstract class SubmitUiEvent {} O b s e r v a b l e . m e r g e ( s u b m i t E v e n t s , c h e c k N a m e E v e n t s ) class SubmitEventZextends SubmitUiEventY{ /* ... */ } class CheckNameEvent extends SubmitUiEvent { /* ... */ } Observable submitEvents = RxView.clicks(submitView) .map(ignored -> new SubmitEvent(nameView.getText().toString())); Observable checkNameEvents = RxTextView.afterTextChanges(nameView) .map(text -> new CheckNameEvent(text));

Slide 165

Slide 165 text

Reactive State Observable events = /* ... */; ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); disposables.add(events.compose(submit).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 166

Slide 166 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress()));

Slide 167

Slide 167 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = events -> events .switchMap(event -> event .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(event -> service.checkName(event.name)) .map(response -> ???) .onErrorReturn(t -> ???) .observeOn(AndroidSchedulers.mainThread()) .startWith(???));

Slide 168

Slide 168 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = events -> events .switchMap(event -> event .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(event -> service.checkName(event.name)) .map(response -> ???) .onErrorReturn(t -> ???) .observeOn(AndroidSchedulers.mainThread()) .startWith(???));

Slide 169

Slide 169 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = events -> events .switchMap(event -> event .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(event -> service.checkName(event.name)) .map(response -> ???) .onErrorReturn(t -> ???) .observeOn(AndroidSchedulers.mainThread()) .startWith(???));

Slide 170

Slide 170 text

Reactive State ObservableTransformer submit = events -> events .flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = events -> events .switchMap(event -> event .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(event -> service.checkName(event.name)) .map(response -> ???) .onErrorReturn(t -> ???) .observeOn(AndroidSchedulers.mainThread()) .startWith(???));

Slide 171

Slide 171 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */;

Slide 172

Slide 172 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???;

Slide 173

Slide 173 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???; events

Slide 174

Slide 174 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???; events checkName submit

Slide 175

Slide 175 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???; events models checkName submit

Slide 176

Slide 176 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???; events models checkName submit Observable.merge(…)

Slide 177

Slide 177 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???; events models checkName submit Observable.merge(…) Observable.publish(…);

Slide 178

Slide 178 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> ???; Observable.merge(…) Observable.publish(…);

Slide 179

Slide 179 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> events.publish(shared -> Observable.merge( );Z …) Observable …ZG

Slide 180

Slide 180 text

Reactive State ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */; ObservableTransformer submitUi = events -> events.publish(shared -> Observable.merge( shared.ofType(SubmitEvent.class).compose(submit), shared.ofType(CheckNameEvent.class).compose(checkName)));

Slide 181

Slide 181 text

Reactive State Observable events = /* ... */; ObservableTransformer submitUi = events -> events.publish(shared -> Observable.merge( shared.ofType(SubmitEvent.class).compose(submit), shared.ofType(CheckNameEvent.class).compose(checkName))); disposables.add(events.compose(submitUi).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); })); ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */;

Slide 182

Slide 182 text

Reactive State Observable events = /* ... */; ObservableTransformer submitUi = events -> events.publish(shared -> Observable.merge( shared.ofType(SubmitEvent.class).compose(submit), shared.ofType(CheckNameEvent.class).compose(checkName))); disposables.add(events.compose(submitUi).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); }));

Slide 183

Slide 183 text

Reactive State Observable events = /* ... */; ObservableTransformer submitUi = events -> events.publish(shared -> Observable.merge( shared.ofType(SubmitEvent.class).compose(submit), shared.ofType(CheckNameEvent.class).compose(checkName))); disposables.add(events.compose(submitUi).subscribe(model -> { submitView.setEnabled(!model.inProgress); progressView.setVisibility(model.inProgress ? VISIBLE : GONE); if (!model.inProgress) { if (model.success) finish() else Toast.makeText(this, "Failed to set name: " + model.message, LENGTH_SHORT).show(); }X }, t -> { throw new OnErrorNotImplementedException(t); })); ObservableTransformer submit = /* ... */; ObservableTransformer checkName = /* ... */;

Slide 184

Slide 184 text

Reactive State

Slide 185

Slide 185 text

Reactive State

Slide 186

Slide 186 text

Reactive State Observable

Slide 187

Slide 187 text

Reactive State Observable Observable

Slide 188

Slide 188 text

Reactive State Observable Observable Observable

Slide 189

Slide 189 text

Reactive State Observable Observable Observable Observable

Slide 190

Slide 190 text

Reactive State Observable Observable Observable Observable UiEventZ

Slide 191

Slide 191 text

Reactive State Observable Observable Observable Observable UiModelZ

Slide 192

Slide 192 text

Reactive State Observable Observable Observable Observable

Slide 193

Slide 193 text

Reactive State Observable Observable Observable Observable

Slide 194

Slide 194 text

Reactive State Observable Observable Observable Observable

Slide 195

Slide 195 text

Reactive State final class SubmitUiModel { final boolean inProgress; final boolean success; final String errorMessage; private SubmitUiModel( boolean inProgress, boolean success, String errorMessage) { // ... } static SubmitUiModel inProgress() { /* ... */ } static SubmitUiModel success() { /* ... */ } static SubmitUiModel failure(String errorMessage) { /* ... */ } }

Slide 196

Slide 196 text

Reactive State inProgress false success false errorMessage null

Slide 197

Slide 197 text

Reactive State inProgress false success false errorMessage null CheckNameResult.IN_FLIGHT

Slide 198

Slide 198 text

Reactive State inProgress false success false errorMessage null CheckNameResult.IN_FLIGHT inProgress true success false errorMessage null CheckNameResult.SUCC

Slide 199

Slide 199 text

Reactive State rogress se cess se orMessage l CheckNameResult.IN_FLIGHT inProgress true success false errorMessage null CheckNameResult.SUCCESS i f s f e n

Slide 200

Slide 200 text

Reactive State ckNameResult.IN_FLIGHT inProgress true success false errorMessage null CheckNameResult.SUCCESS inProgress false success false errorMessage null Ch

Slide 201

Slide 201 text

Reactive State rogress e cess se orMessage l CheckNameResult.SUCCESS inProgress false success false errorMessage null CheckNameResult.IN_FLIGHT i t s f e n

Slide 202

Slide 202 text

Reactive State ckNameResult.SUCCESS inProgress false success false errorMessage null CheckNameResult.IN_FLIGHT inProgress true success false errorMessage null Su

Slide 203

Slide 203 text

Reactive State nProgress alse uccess alse rrorMessage ull CheckNameResult.IN_FLIGHT inProgress true success false errorMessage null SubmitResult.IN_FLIGHT i t s f e n

Slide 204

Slide 204 text

Reactive State eckNameResult.IN_FLIGHT inProgress true success false errorMessage null SubmitResult.IN_FLIGHT inProgress true success false errorMessage null Su

Slide 205

Slide 205 text

Reactive State T inProgress true success false errorMessage null SubmitResult.IN_FLIGHT inProgress true success false errorMessage null SubmitResult.SUCCESS i f s t e n

Slide 206

Slide 206 text

Reactive State SubmitResult.IN_FLIGHT inProgress true success false errorMessage null SubmitResult.SUCCESS inProgress false success true errorMessage null

Slide 207

Slide 207 text

Reactive State SubmitUiModel initialState = SubmitUiModel.idle();

Slide 208

Slide 208 text

Reactive State SubmitUiModel initialState = SubmitUiModel.idle(); Observable results = /* ... */;

Slide 209

Slide 209 text

Reactive State SubmitUiModel initialState = SubmitUiModel.idle(); Observable results = /* ... */; Observable uiModels = results .scan(initialState, (state, result) -> /* ... */);

Slide 210

Slide 210 text

Reactive State SubmitUiModel initialState = SubmitUiModel.idle(); Observable results = /* ... */; Observable uiModels = results .scan(initialState, (state, result) -> { if (result == CheckNameResult.IN_FLIGHT || result == SubmitResult.IN_FLIGHT) return SubmitUiModel.inProgress(); if (result == CheckNameResult.SUCCESS) return SubmitUiModel.idle(); if (result == SubmitResult.SUCCESS) return SubmitUiModel.success(); // TODO handle check name and submit failures... throw new IllegalArgumentException("Unknown result: " + result); }); /* ... */

Slide 211

Slide 211 text

Reactive State ObservableTransformer submit = events -> events.flatMap(event -> service.setName(event.name) .map(response -> SubmitUiModel.success()) .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage())) .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = events -> events.switchMap(event -> event .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(event -> service.checkName(event.name)) .map(response -> ???) .onErrorReturn(t -> ???) .observeOn(AndroidSchedulers.mainThread()) .startWith(???));

Slide 212

Slide 212 text

Reactive State ObservableTransformer submit = actions -> actions.flatMap(action -> service.setName(action.name) .map(response -> SubmitUiModel.success())A .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage()))B .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = actions -> actions.switchMap(action -> action .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(action -> service.checkName(action.name)) .map(response -> ???)Y .onErrorReturn(t -> ???)Z .observeOn(AndroidSchedulers.mainThread()) .startWith(???)); SubmitEvent SubmitUiModel events events event event CheckNameEvent SubmitUiModel events events event event event event

Slide 213

Slide 213 text

Reactive State ObservableTransformer submit = actions -> actions.flatMap(action -> service.setName(action.name) .map(response -> SubmitUiModel.success())A .onErrorReturn(t -> SubmitUiModel.failure(t.getMessage()))B .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitUiModel.inProgress())); ObservableTransformer checkName = actions -> actions.switchMap(action -> action .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(action -> service.checkName(action.name)) .map(response -> ???)Y .onErrorReturn(t -> ???)Z .observeOn(AndroidSchedulers.mainThread()) .startWith(???));

Slide 214

Slide 214 text

Reactive State ObservableTransformer submit = actions -> actions.flatMap(action -> service.setName(action.name) .map(response -> SubmitResult.SUCCESS)A .onErrorReturn(t -> SubmitResult.failure(t.getMessage()))B .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitResult.IN_FLIGHT)); ObservableTransformer checkName = actions -> actions.switchMap(action -> action .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(action -> service.checkName(action.name)) .map(response -> CheckNameResult.SUCCESS)Y .onErrorReturn(t -> CheckNameResult.failure(t.getMessage()))Z .observeOn(AndroidSchedulers.mainThread()) .startWith(CheckNameResult.IN_FLIGHT)); SubmitUiModel.success() SubmitUiModel.failure(t.getMessage()) SubmitUiModel.inProgress() ??? ??? ???

Slide 215

Slide 215 text

Reactive State ObservableTransformer submit = actions -> actions.flatMap(action -> service.setName(action.name) .map(response -> SubmitResult.SUCCESS)A .onErrorReturn(t -> SubmitResult.failure(t.getMessage()))B .observeOn(AndroidSchedulers.mainThread()) .startWith(SubmitResult.IN_FLIGHT)); ObservableTransformer checkName = actions -> actions.switchMap(action -> action .delay(200, MILLISECONDS, AndroidSchedulers.mainThread()) .flatMap(action -> service.checkName(action.name)) .map(response -> CheckNameResult.SUCCESS)Y .onErrorReturn(t -> CheckNameResult.failure(t.getMessage()))Z .observeOn(AndroidSchedulers.mainThread()) .startWith(CheckNameResult.IN_FLIGHT));

Slide 216

Slide 216 text

No content

Slide 217

Slide 217 text

Observable

Slide 218

Slide 218 text

Observable Observable

Slide 219

Slide 219 text

Observable Observable Observable

Slide 220

Slide 220 text

Observable Observable Observable Observable

Slide 221

Slide 221 text

Observable Observable Observable Observable Log.d

Slide 222

Slide 222 text

Observable Observable Observable Observable Log.d

Slide 223

Slide 223 text

Observable Observable Observable Observable Subject TestObserver

Slide 224

Slide 224 text

Observable Observable Observable Observable

Slide 225

Slide 225 text

Observable Observable TestObserver Subject

Slide 226

Slide 226 text

Observable Observable Observable Observable

Slide 227

Slide 227 text

Observable Observable Observable Observable Redux / Cycle

Slide 228

Slide 228 text

jakewharton jakewharton jakewharton twitter.com/ github.com/ .com Managing State with RxJava