Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Exploring RxJava 2 for Android (GOTOcph October 2016)

Exploring RxJava 2 for Android (GOTOcph October 2016)

This talk will be an exploration on why reactive programming works so well for Android and how to use RxJava to apply it.

Video: https://www.youtube.com/watch?v=htIXKI5gOQU

Jake Wharton

October 03, 2016
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

  1. Exploring RxJava
    Jake Wharton

    View full-size slide

  2. Exploring RxJava 2
    Jake Wharton

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  5. Why Reactive?
    interface UserManager {
    User getUser();

    }A

    View full-size slide

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

    }A

    View full-size slide

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

    }A
    UserManager um = new UserManager();

    View full-size slide

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

    }A
    UserManager um = new UserManager();
    System.out.println(um.getUser());

    View full-size slide

  9. 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");

    View full-size slide

  10. 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());

    View full-size slide

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

    }A

    View full-size slide

  12. 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());

    View full-size slide

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

    }A

    View full-size slide

  14. 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", new Runnable() {
    @Override public void run() {
    System.out.println(um.getUser());
    }X
    });

    View full-size slide

  15. 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

    View full-size slide

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

    View full-size slide

  17. 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
    });

    View full-size slide

  18. 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

    View full-size slide

  19. 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
    });

    View full-size slide

  20. 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

    View full-size slide

  21. 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

    View full-size slide

  22. 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

    View full-size slide

  23. 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

    View full-size slide

  24. 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

    View full-size slide

  25. 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

    View full-size slide

  26. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  32. Why Reactive?

    View full-size slide

  33. Why Reactive?

    View full-size slide

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

    View full-size slide

  35. Why Reactive?

    View full-size slide

  36. Why Reactive?

    View full-size slide

  37. Why Reactive?

    View full-size slide

  38. Why Reactive?

    View full-size slide

  39. Why Reactive?

    View full-size slide

  40. Why Reactive?

    View full-size slide

  41. RxJava
    • A set of classes for representing sources of data.

    View full-size slide

  42. RxJava
    • A set of classes for representing sources of data.
    • A set of classes for listening to data sources.

    View full-size slide

  43. RxJava
    • A set of classes for representing sources of data.
    • A set of classes for listening to data sources.
    • A set of methods for modifying and composing the data.

    View full-size slide

  44. RxJava
    • A set of classes for representing sources of data.
    • A set of classes for listening to data sources.
    • A set of methods for modifying and composing the data.

    View full-size slide

  45. Sources
    • Usually do work when you start or stop listening.

    View full-size slide

  46. Sources
    • Usually do work when you start or stop listening.
    • Synchronous or asynchronous.

    View full-size slide

  47. Sources
    • Usually do work when you start or stop listening.
    • Synchronous or asynchronous.
    • Single item or many items.

    View full-size slide

  48. Sources
    • Usually do work when you start or stop listening.
    • Synchronous or asynchronous.
    • Single item, many items, or empty.

    View full-size slide

  49. Sources
    • Usually do work when you start or stop listening.
    • Synchronous or asynchronous.
    • Single item, many items, or empty.
    • Terminates with an error or succeeds to completion.

    View full-size slide

  50. Sources
    • Usually do work when you start or stop listening.
    • Synchronous or asynchronous.
    • Single item, many items, or empty.
    • Terminates with an error or succeeds to completion.
    • May never terminate!

    View full-size slide

  51. Sources
    • Usually do work when you start or stop listening.
    • Synchronous or asynchronous.
    • Single item, many items, or empty.
    • Terminates with an error or succeeds to completion.
    • May never terminate!
    • Just an implementation of the Observer pattern.

    View full-size slide

  52. • Observable
    • Flowable
    void
    void

    Sources

    View full-size slide

  53. • Observable
    • Emits 0 to n items.
    • Terminates with complete or error.
    • Flowable
    • Emits 0 to n items.
    • Terminates with complete or error.
    void
    void

    Sources

    View full-size slide

  54. • Observable
    • Emits 0 to n items.
    • Terminates with complete or error.
    • Does not have backpressure.
    • Flowable
    • Emits 0 to n items.
    • Terminates with complete or error.
    • Has backpressure.
    void
    void

    Sources

    View full-size slide

  55. Flowable vs. Observable

    View full-size slide

  56. Flowable vs. Observable
    • Backpressure allows you to control how fast a source emits items.

    View full-size slide

  57. Flowable vs. Observable
    • Backpressure allows you to control how fast a source emits items.
    • RxJava 1.x added backpressure late in the design process.

    View full-size slide

  58. Flowable vs. Observable
    • Backpressure allows you to control how fast a source emits items.
    • RxJava 1.x added backpressure late in the design process.
    • All types exposed backpressure but not all sources respected it.

    View full-size slide

  59. Flowable vs. Observable
    • Backpressure allows you to control how fast a source emits items.
    • RxJava 1.x added backpressure late in the design process.
    • All types exposed backpressure but not all sources respected it.
    • Backpressure, like inheritance, must be designed for.

    View full-size slide

  60. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.

    View full-size slide

  61. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);

    View full-size slide

  62. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);
    Observable rows
    = db.createQuery("SELECT * …");

    View full-size slide

  63. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);
    Observable rows
    = db.createQuery("SELECT * …");

    View full-size slide

  64. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);
    Observable rows
    = db.createQuery("SELECT * …");

    View full-size slide

  65. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);
    Observable rows
    = db.createQuery("SELECT * …");

    View full-size slide

  66. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);
    Observable rows
    = db.createQuery("SELECT * …");
    MissingBackpressureException

    View full-size slide

  67. Flowable vs. Observable
    • Backpressure, like inheritance, must be designed for.
    Observable events
    = RxView.touches(paintView);
    Flowable rows
    = db.createQuery("SELECT * …");

    View full-size slide

  68. Flowable vs. Observable
    Observable Flowable

    View full-size slide

  69. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B

    View full-size slide

  70. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B

    View full-size slide

  71. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B

    View full-size slide

  72. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B

    View full-size slide

  73. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B

    View full-size slide

  74. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B
    interface Disposable {

    void dispose();

    }B

    View full-size slide

  75. Flowable vs. Observable
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B
    interface Disposable {

    void dispose();

    }B
    interface Subscription {

    void cancel();

    void request(long r);

    }B

    View full-size slide

  76. Backpressure No Backpressure
    0…n items, complete|error Flowable Observable

    View full-size slide

  77. Reactive Streams
    ...is an initiative to provide a standard
    for asynchronous stream processing
    with non-blocking back pressure.

    View full-size slide

  78. Reactive Streams
    interface Publisher {

    void subscribe(Subscriber super T> s);

    }A

    View full-size slide

  79. Reactive Streams
    interface Publisher {

    void subscribe(Subscriber super T> s);

    }A
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B

    View full-size slide

  80. Reactive Streams
    interface Publisher {

    void subscribe(Subscriber super T> s);

    }A
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Subscription {

    void request(long n);

    void cancel();

    }C

    View full-size slide

  81. Reactive Streams
    interface Publisher {

    void subscribe(Subscriber super T> s);

    }A
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Subscription {

    void request(long n);

    void cancel();

    }C
    interface Processor extends Subscriber, Publisher {

    }D


    View full-size slide

  82. Backpressure No Backpressure
    0…n items, complete|error Flowable Observable

    View full-size slide

  83. Reactive Streams
    (Backpressure)
    No Backpressure
    0…n items, complete|error Flowable Observable

    View full-size slide

  84. interface UserManager {
    User getUser();
    void setName(String name);
    void setAge(int age);

    }A
    Sources

    View full-size slide

  85. Sources
    interface UserManager {
    Observable getUser();
    void setName(String name);
    void setAge(int age);

    }A

    View full-size slide

  86. Source Specializations

    View full-size slide

  87. Source Specializations
    • Encoding subsets of Observable into the type system.

    View full-size slide

  88. Single
    • Either succeeds with an item or errors.
    • No backpressure support.

    View full-size slide

  89. Single
    • Either succeeds with an item or errors.
    • No backpressure support.
    • Think "reactive scalar".

    View full-size slide

  90. Completable
    • Either completes or errors. Has no items!
    • No backpressure support.

    View full-size slide

  91. Completable
    • Either completes or errors. Has no items!
    • No backpressure support.
    • Think "reactive runnable".

    View full-size slide

  92. Maybe
    • Either succeeds with an item, completes with no items, or errors.
    • No backpressure support.

    View full-size slide

  93. Maybe
    • Either succeeds with an item, completes with no items, or errors.
    • No backpressure support.
    • Think "reactive optional".

    View full-size slide

  94. Source Specializations
    • Encoding subsets of Observable into the type system.
    • Single – Item or error. Think "scalar".
    • Completable – Complete or error. Think "runnable".
    • Maybe – Item, complete, or error. Think "optional".

    View full-size slide

  95. Reactive Streams
    (Backpressure)
    No Backpressure
    0…n items, complete|error Flowable Observable
    item|complete|error Maybe
    item|error Single
    complete|error Completable

    View full-size slide

  96. Sources
    interface UserManager {
    Observable getUser();
    void setName(String name);
    void setAge(int age);

    }A

    View full-size slide

  97. Sources
    interface UserManager {
    Observable getUser();
    Completable setName(String name);
    Completable setAge(int age);

    }A
    void
    void


    View full-size slide

  98. Creating Sources

    View full-size slide

  99. Creating Sources
    Flowable.just("Hello");

    Flowable.just("Hello", "World");

    Observable.just("Hello");

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

    Maybe.just("Hello");

    Single.just("Hello");

    View full-size slide

  100. Creating Sources
    String[] array = { "Hello", "World" };

    List list = Arrays.asList(array);

    Flowable.fromArray(array);
    Flowable.fromIterable(list);
    Observable.fromArray(array);
    Observable.fromIterable(list);

    View full-size slide

  101. Creating Sources
    Observable.fromCallable(new Callable() {

    @Override public String call() {Y

    return getName();

    }X

    });

    View full-size slide

  102. Creating Sources
    Observable.fromCallable(new Callable() {

    @Override public String call() throws Exception {Y

    return getName();Z

    }X

    });

    View full-size slide

  103. Creating Sources
    OkHttpClient client = // …
    Request request = // …
    Observable.fromCallable(new Callable() {

    @Override public String call() throws Exception {Y

    return client.newCall(request).execute();Z

    }X

    });


    getName()

    View full-size slide

  104. Creating Sources
    Flowable.fromCallable(() -> "Hello");


    Observable.fromCallable(() -> "Hello");


    Maybe.fromCallable(() -> "Hello");


    Single.fromCallable(() -> "Hello");


    Completable.fromCallable(() -> "Ignored!");

    View full-size slide

  105. Creating Sources
    Flowable.fromCallable(() -> "Hello");


    Observable.fromCallable(() -> "Hello");


    Maybe.fromCallable(() -> "Hello");

    Maybe.fromAction(() -> System.out.println("Hello"));

    Maybe.fromRunnable(() -> System.out.println("Hello"))


    Single.fromCallable(() -> "Hello");


    Completable.fromCallable(() -> "Ignored!");

    Completable.fromAction(() -> System.out.println("Hello"));

    Completable.fromRunnable(() -> System.out.println("Hello"));

    View full-size slide

  106. Creating Sources
    Observable.create();

    View full-size slide

  107. Creating Sources
    Observable.create(new ObservableOnSubscribe() {

    @Override

    public void subscribe(ObservableEmitter e) throws Exception {

    e.onNext("Hello");

    e.onComplete();

    }X

    });

    View full-size slide

  108. Creating Sources
    Observable.create(new ObservableOnSubscribe() {

    @Override

    public void subscribe(ObservableEmitter e) throws Exception {

    e.onNext("Hello");

    e.onComplete();

    }X

    });

    View full-size slide

  109. Creating Sources
    Observable.create(new ObservableOnSubscribe() {

    @Override

    public void subscribe(ObservableEmitter e) throws Exception {

    e.onNext("Hello");

    e.onComplete();

    }X

    });

    View full-size slide

  110. Creating Sources
    Observable.create(new ObservableOnSubscribe() {

    @Override

    public void subscribe(ObservableEmitter e) throws Exception {

    e.onNext("Hello");

    e.onComplete();

    }X

    });

    View full-size slide

  111. Creating Sources
    Observable.create(e -> {

    e.onNext("Hello");

    e.onComplete();

    });

    View full-size slide

  112. Creating Sources
    Observable.create(e -> {

    e.onNext("Hello");
    e.onNext("World");

    e.onComplete();

    });

    View full-size slide

  113. Creating Sources
    OkHttpClient client = // …
    Request request = // …
    Observable.create(e -> {
    client.newCall(request).enqueue(new Callback() {
    @Override public void onResponse(Response r) throws IOException {
    e.onNext(r.body().string());
    e.onComplete();
    }A
    @Override public void onFailure(IOException e) {
    e.onError(e);
    }B
    });

    });

    View full-size slide

  114. Creating Sources
    OkHttpClient client = // …
    Request request = // …
    Observable.create(e -> {
    Call call = client.newCall(request);
    call.enqueue(new Callback() {
    @Override public void onResponse(Response r) throws IOException {
    e.onNext(r.body().string());
    e.onComplete();
    }A
    @Override public void onFailure(IOException e) {
    e.onError(e);
    }B
    });

    });

    View full-size slide

  115. Creating Sources
    OkHttpClient client = // …
    Request request = // …
    Observable.create(e -> {
    Call call = client.newCall(request);
    e.setCancelation(() -> call.cancel());
    call.enqueue(new Callback() {
    @Override public void onResponse(Response r) throws IOException {
    e.onNext(r.body().string());
    e.onComplete();
    }A
    @Override public void onFailure(IOException e) {
    e.onError(e);
    }B
    });

    });

    View full-size slide

  116. Creating Sources
    OkHttpClient client = // …
    Request request = // …
    Observable.create(e -> {
    Call call = client.newCall(request);
    e.setCancelation(() -> call.cancel());
    call.enqueue(new Callback() {
    @Override public void onResponse(Response r) throws IOException {
    e.onNext(r.body().string());
    e.onComplete();
    }A
    @Override public void onFailure(IOException e) {
    e.onError(e);
    }B
    });

    });

    View full-size slide

  117. Creating Sources
    View view = // …
    Observable.create(e -> {
    e.setCancelation(() -> view.setOnClickListener(null));
    view.setOnClickListener(v -> e.onNext(v));

    });

    View full-size slide

  118. Creating Sources
    Flowable.create(e -> { … });
    Observable.create(e -> { … });
    Maybe.create(e -> { … });
    Single.create(e -> { … });
    Completable.create(e -> { … });

    View full-size slide

  119. Observing Sources

    View full-size slide

  120. Observing Sources
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Disposable d);

    }B

    View full-size slide

  121. Observing Sources
    Observable Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Observer {

    void onNext(T t);A

    void onComplete();B

    void onError(Throwable t);C

    void onSubscribe(Disposable d);D

    }B
    interface Disposable {

    void dispose();

    }B
    interface Subscription {

    void cancel();

    void request(long r);

    }B

    View full-size slide

  122. Observing Sources
    Observable o = Observable.just("Hello");
    o.subscribe(new Observer() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    @Override public void onSubscribe(Disposable d) {
    ???
    }B

    });
    Flowable
    interface Subscriber {

    void onNext(T t);

    void onComplete();

    void onError(Throwable t);

    void onSubscribe(Subscription s);

    }B
    interface Disposable {

    void dispose();

    }B
    interface Subscription {

    void cancel();

    void request(long r);

    }B
    interface T

    T t ;A

    ;B

    ;C

    ;D


    View full-size slide

  123. Observing Sources
    Observable o = Observable.just("Hello");
    o.subscribe(new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    });




    @Override public void onSubscribe(Disposable d) {
    ???
    }B


    View full-size slide

  124. Observing Sources
    Observable o = Observable.just("Hello");
    o.subscribe(new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    });Z
    // TODO how do we dispose???

    View full-size slide

  125. Observing Sources
    Observable o = Observable.just("Hello");
    DisposableObserver observer = new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    }
    o.subscribe(observer);Z
    // TODO how do we dispose??????

    View full-size slide

  126. Observing Sources
    Observable o = Observable.just("Hello");
    DisposableObserver observer = new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    }
    o.subscribe(observer);Z
    observer.dispose();

    View full-size slide

  127. Observing Sources
    Observable o = Observable.just("Hello");
    o.subscribe(new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    });Z

    View full-size slide

  128. Observing Sources
    Observable o = Observable.just("Hello");
    o.subscribeWith(new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    });Z

    View full-size slide

  129. Observing Sources
    Observable o = Observable.just("Hello");
    Disposable d = o.subscribeWith(new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    });Z
    d.dispose();

    View full-size slide

  130. Observing Sources
    Observable o = Observable.just("Hello");
    CompositeDisposable disposables = new CompositeDisposable();
    disposables.add(o.subscribeWith(new DisposableObserver() {

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    }));Z
    disposables.dispose();




    d.dispose();
    Disposable d =

    View full-size slide

  131. Observing Sources
    Observable o = Observable.just("Hello");
    o.subscribeWith(new DisposableObserver() { … });Z
    Maybe m = Maybe.just("Hello");
    m.subscribeWith(new DisposableMaybeObserver() { … });Z
    Single s = Single.just("Hello");
    s.subscribeWith(new DisposableSingleObserver() { … });Z
    Completable c = Completable.completed();
    c.subscribeWith(new DisposableCompletableObserver() { … });Z
    disposables.add(

    @Override public void onNext(String s) { … }

    @Override public void onComplete() { … }

    @Override public void onError(Throwable t) { … }

    )
    disposables.dispose();

    View full-size slide

  132. Observing Sources
    Flowable f = Flowable.just("Hello");
    f.subscribeWith(new DisposableSubscriber() { … });
    Observable o = Observable.just("Hello");
    o.subscribeWith(new DisposableObserver() { … });
    Maybe m = Maybe.just("Hello");
    m.subscribeWith(new DisposableMaybeObserver() { … });
    Single s = Single.just("Hello");
    s.subscribeWith(new DisposableSingleObserver() { … });
    Completable c = Completable.completed();
    c.subscribeWith(new DisposableCompletableObserver() { … });

    View full-size slide

  133. Observing Sources
    Flowable f = Flowable.just("Hello");
    f.subscribeWith(new DisposableSubscriber() { … });
    Observable o = Observable.just("Hello");
    o.subscribeWith(new DisposableObserver() { … });
    Maybe m = Maybe.just("Hello");
    m.subscribeWith(new DisposableMaybeObserver() { … });
    Single s = Single.just("Hello");
    s.subscribeWith(new DisposableSingleObserver() { … });
    Completable c = Completable.completed();
    c.subscribeWith(new DisposableCompletableObserver() { … });

    View full-size slide

  134. Observing Sources
    Flowable f = Flowable.just("Hello");
    Disposable d1 = f.subscribeWith(new DisposableSubscriber() { … });
    Observable o = Observable.just("Hello");
    Disposable d2 = o.subscribeWith(new DisposableObserver() { … });
    Maybe m = Maybe.just("Hello");
    Disposable d3 = m.subscribeWith(new DisposableMaybeObserver() { … });
    Single s = Single.just("Hello");
    Disposable d4 = s.subscribeWith(new DisposableSingleObserver() { … });
    Completable c = Completable.completed();
    Disposable d5 = c.subscribeWith(new DisposableCompletableObserver() { … });

    View full-size slide

  135. RxJava
    • A set of classes for representing sources of data.
    • A set of classes for listening to data sources.
    • A set of methods for modifying and composing data.

    View full-size slide

  136. RxJava
    • A set of classes for representing sources of data.
    • A set of classes for listening to data sources.
    • A set of methods for modifying and composing data.

    View full-size slide

  137. Operators
    • Manipulate or combine data in some way.

    View full-size slide

  138. Operators
    • Manipulate or combine data in some way.
    • Manipulate threading in some way.

    View full-size slide

  139. Operators
    • Manipulate or combine data in some way.
    • Manipulate threading in some way.
    • Manipulate emissions in some way.

    View full-size slide

  140. Operators
    String greeting = "Hello";

    View full-size slide

  141. Operators
    String greeting = "Hello";Z
    String yelling = greeting.toUppercase();

    View full-size slide

  142. Operators
    Observable greeting = Observable.just("Hello");Z
    String yelling = greeting.toUppercase();Y

    View full-size slide

  143. Operators
    Observable greeting = Observable.just("Hello");
    Observable yelling = greeting.map(s -> s.toUppercase());Y

    View full-size slide

  144. Operators
    Observable greeting = Observable.just("Hello");
    Observable yelling = greeting.map(s -> s.toUppercase());Y

    View full-size slide

  145. Operators
    @Override public void success() {
    runOnUiThread(new Runnable() {
    @Override public void run() {
    tv.setText(um.getUser().toString());
    }4
    });
    }A

    View full-size slide

  146. Operators
    Observable user = um.getUser();

    View full-size slide

  147. Operators
    Observable user = um.getUser();
    Observable mainThreadUser =
    user.observeOn(AndroidSchedulers.mainThread());

    View full-size slide

  148. Operators
    Observable user = um.getUser();
    Observable mainThreadUser =
    user.observeOn(AndroidSchedulers.mainThread());

    View full-size slide

  149. Operators
    OkHttpClient client = // …
    Request request = // …
    Response response = client.newCall(request).execute();

    View full-size slide

  150. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    });

    View full-size slide

  151. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    });
    Observable backgroundResponse =
    response.subscribeOn(Schedulers.io());

    View full-size slide

  152. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    });
    Observable backgroundResponse =
    response.subscribeOn(Schedulers.io());

    View full-size slide

  153. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    });
    Observable backgroundResponse =
    response.subscribeOn(Schedulers.io());

    View full-size slide

  154. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    })
    .subscribeOn(Schedulers.io());Y

    View full-size slide

  155. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread());Y

    View full-size slide

  156. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .map(response -> response.body().string());Y

    View full-size slide

  157. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    })
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .map(response -> response.body().string());Y// NetworkOnMainThread!

    View full-size slide

  158. Operators
    OkHttpClient client = // …
    Request request = // …
    Observable response = Observable.fromCallable(() -> {
    return client.newCall(request).execute();
    })
    .subscribeOn(Schedulers.io())
    .map(response -> response.body().string()) // Ok!
    .observeOn(AndroidSchedulers.mainThread());Y// NetworkOnMainThread!

    View full-size slide

  159. Operator Specialization

    View full-size slide

  160. Operator Specialization
    Observable

    View full-size slide

  161. Operator Specialization
    first()
    Observable

    View full-size slide

  162. Operator Specialization
    first()
    Observable
    Observable

    View full-size slide

  163. Operator Specialization
    1 2 3 4 5 6 7 8 9 10 11
    first()
    1
    Observable
    Observable

    View full-size slide

  164. Operator Specialization
    1 2 3 4 5 6 7 8 9 10 11
    get(0)
    1
    List
    List

    View full-size slide

  165. Operator Specialization
    first()
    Observable
    Observable

    View full-size slide

  166. Operator Specialization
    first()
    Observable
    Single

    View full-size slide

  167. Operator Specialization
    1 2 3 4 5 6 7 8 9 10 11
    first()
    1
    Observable
    Single

    View full-size slide

  168. Operator Specialization
    first()
    Observable
    Single

    View full-size slide

  169. Operator Specialization
    first()
    Observable
    Single
    NoSuchElementException

    View full-size slide

  170. Operator Specialization
    first()
    Observable

    View full-size slide

  171. Operator Specialization
    firstElement()
    Observable

    View full-size slide

  172. Operator Specialization
    firstElement()
    Observable
    Maybe

    View full-size slide

  173. Operator Specialization
    firstElement()
    Observable
    Maybe

    View full-size slide

  174. Operator Specialization
    ignoreElements()
    Observable

    View full-size slide

  175. Operator Specialization
    ignoreElements()
    Observable
    Completable

    View full-size slide

  176. Operator Specialization
    1 2 3 4 5 6 7 8 9
    ignoreElements()
    Observable
    Completable

    View full-size slide

  177. Operator Specialization
    ignoreElements()
    Flowable
    Completable

    View full-size slide

  178. Operator Specialization
    firstElement()
    Flowable
    Maybe

    View full-size slide

  179. Operator Specialization
    first()
    Flowable
    Single

    View full-size slide

  180. Flowable Observable Maybe Single Completable
    Flowable toObservable()
    reduce()
    elementAt()
    firstElement()
    lastElement()
    singleElement()
    scan()
    elementAt()
    first()/firstOrError()
    last()/lastOrError()
    single/singleOrError()
    all()/any()/count()
    (and more)
    ignoreElements()
    Observable toFlowable()
    reduce()
    elementAt()
    firstElement()
    lastElement()
    singleElement()
    scan()
    elementAt()
    first()/firstOrError()
    last()/lastOrError()
    single/singleOrError()
    all()/any()/count()
    (and more)
    ignoreElements()
    Maybe toFlowable() toObservable()
    toSingle()
    sequenceEqual()
    toCompletable()
    Single toFlowable() toObservable() toMaybe() toCompletable()
    Completable toFlowable() toObservable() toMaybe()
    toSingle()
    toSingleDefault()
    From
    To

    View full-size slide

  181. Flowable Observable Maybe Single Completable
    Flowable toObservable()
    reduce()
    elementAt()
    firstElement()
    lastElement()
    singleElement()
    scan()
    elementAt()
    first()/firstOrError()
    last()/lastOrError()
    single/singleOrError()
    all()/any()/count()
    (and more)
    ignoreElements()
    Observable toFlowable()
    reduce()
    elementAt()
    firstElement()
    lastElement()
    singleElement()
    scan()
    elementAt()
    first()/firstOrError()
    last()/lastOrError()
    single/singleOrError()
    all()/any()/count()
    (and more)
    ignoreElements()
    Maybe toFlowable() toObservable()
    toSingle()
    sequenceEqual()
    toCompletable()
    Single toFlowable() toObservable() toMaybe() toCompletable()
    Completable toFlowable() toObservable() toMaybe()
    toSingle()
    toSingleDefault()
    From
    To

    View full-size slide

  182. Flowable Observable Maybe Single Completable
    Flowable toObservable()
    reduce()
    elementAt()
    firstElement()
    lastElement()
    singleElement()
    scan()
    elementAt()
    first()/firstOrError()
    last()/lastOrError()
    single/singleOrError()
    all()/any()/count()
    (and more)
    ignoreElements()
    Observable toFlowable()
    reduce()
    elementAt()
    firstElement()
    lastElement()
    singleElement()
    scan()
    elementAt()
    first()/firstOrError()
    last()/lastOrError()
    single/singleOrError()
    all()/any()/count()
    (and more)
    ignoreElements()
    Maybe toFlowable() toObservable()
    toSingle()
    sequenceEqual()
    toCompletable()
    Single toFlowable() toObservable() toMaybe() toCompletable()
    Completable toFlowable() toObservable() toMaybe()
    toSingle()
    toSingleDefault()
    From
    To

    View full-size slide

  183. Being Reactive

    View full-size slide

  184. Being Reactive
    um.getUser()

    View full-size slide

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

    View full-size slide

  186. 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 */ }
    });

    View full-size slide

  187. 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

    View full-size slide

  188. 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

    View full-size slide

  189. 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();

    View full-size slide

  190. Being Reactive
    um.setName("Jane Doe")

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  193. 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
    });

    View full-size slide

  194. 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

    View full-size slide

  195. 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

    View full-size slide

  196. Architecture

    View full-size slide

  197. Architecture
    • Less allocation to create a stream.
    • Less overhead when subscribing to a stream.

    View full-size slide

  198. RxJava 2
    • Build an app that reacts properly instead of copes desperately!

    View full-size slide

  199. RxJava 2
    • Build an app that reacts properly instead of copes desperately!
    • Final release scheduled for 2016-10-29.

    View full-size slide

  200. Living with 1.x and 2.x
    class RxJavaInterop {

    static Flowable toV2Flowable(rx.Observable o) { … }

    static Observable toV2Observable(rx.Observable o) { … }
    static Maybe toV2Maybe(rx.Single s) { … }
    static Maybe toV2Maybe(rx.Completable c) { … }

    static Single toV2Single(rx.Single s) { … }

    static Completable toV2Completable(rx.Completable c) { … }

    static rx.Observable toV1Observable(Publisher p) { … }
    static rx.Observable toV1Observable(Observable o, …) { … }

    static rx.Single toV1Single(Single o) { … }
    static rx.Single toV1Single(Maybe m) { … }

    static rx.Completable toV1Completable(Completable c) { … }
    static rx.Completable toV1Completable(Maybe m) { … }

    }X

    View full-size slide

  201. Living with 1.x and 2.x
    class RxJavaInterop {

    static Flowable toV2Flowable(rx.Observable o) { … }

    static Observable toV2Observable(rx.Observable o) { … }
    static Maybe toV2Maybe(rx.Single s) { … }
    static Maybe toV2Maybe(rx.Completable c) { … }

    static Single toV2Single(rx.Single s) { … }

    static Completable toV2Completable(rx.Completable c) { … }

    static rx.Observable toV1Observable(Publisher p) { … }
    static rx.Observable toV1Observable(Observable o, …) { … }

    static rx.Single toV1Single(Single o) { … }
    github.com/akarnokd/RxJava2Interop

    View full-size slide

  202. dependencies {

    compile 'io.reactivex.rxjava2:rxjava:2.0.0-RC3'

    compile 'io.reactivex.rxjava2:rxandroid:2.0.0-RC1'
    // Optionally...

    compile 'com.github.akarnokd:rxjava2-interop:0.3.0'
    }

    View full-size slide

  203. jakewharton
    jakewharton
    jakewharton
    twitter.com/
    google.com/+
    .com
    Exploring RxJava

    View full-size slide