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

Intro to Reactive Programming and RxJava: How t...

Intro to Reactive Programming and RxJava: How to React 😮😱🤪

Approach programming in a new way by using Reactive Programming, a functional style that focuses on the flow and manipulation of data. You already know how to think imperatively, using if-statements and state variables, from your experience programming in C. We will discuss the history of Imperative and Reactive programming and compare the different styles with concrete code examples in Java. By the end of this talk you will understand when to use reactive programming and how powerful and succinct it is for data problems.

Jordan Jozwiak

October 01, 2018
Tweet

More Decks by Jordan Jozwiak

Other Decks in Technology

Transcript

  1. applications ! Retrieving data from a database and then filtering

    out some results based on user settings. 2 3 7
  2. applications ! Retrieving data from a database and then filtering

    out some results based on user settings. ⏳
  3. applications ! Retrieving data from a database and then filtering

    out some results based on user settings. a, b, c -> a, c
  4. applications ! Retrieve data from a database and then filtering

    out some results based on user settings. ! Render a UI that combines data from multiple data sources ! Create a real-time model for stock prices ! Show auto-complete search results to a user ! Log data from a temperature, wind, or pressure sensor
  5. Who actually uses this? ! Very popular in the Android

    community ! Some usage at Google for database requests
  6. Who actually uses this? ! Very popular in the Android

    community ! Some usage at Google for database requests ! Microsoft, Netflix, GitHub, SoundCloud, and more (see reactivex.io)
  7. 4 2 6 OBSERVER observer - “subscribes to” or “consumes”

    data. There can be multiple observers for a single subject. 4 2 1 7 6
  8. 4 2 1 7 6 filter(x -> (x % 2)

    == 0) 4 2 6 SUBJECT OBSERVER
  9. 4 2 1 7 6 filter(x -> (x % 2)

    == 0) 4 2 6 SUBJECT OBSERVER 4 2 6 SERVER 2
  10. 4 2 1 7 6 filter / map / count

    / 
 max / min / delay / ... SUBJECT OBSERVER
  11. ? ? ? ? ? some function that takes ⏳

    ? ? ? ? SUBJECT OBSERVER
  12. ? ? ? ? ? some function that takes ⏳

    ? ? ? ? SUBJECT OBSERVER another function ? ? ? ? ?
  13. What creates the subject data stream? ! These streams are

    called Observables in RxJava ! Observable.create(), fromIterable(), etc.
  14. What creates the subject data stream? ! These streams are

    called Observables in RxJava ! Observable.create(), fromIterable(), etc. ! Retrofitting existing object-oriented design into Observable data streams can be messy
  15. What creates the subject data stream? ! These streams are

    called Observables in RxJava ! Observable.create(), fromIterable(), etc. ! Retrofitting existing object-oriented design into Observable data streams can be messy ! Many, many open-source projects that wrap other implementations into an Rx package (an easy way to get ⭐ ⭐ ⭐ on GitHub)
  16. What creates the subject data stream? ! These streams are

    called Observables in RxJava ! Observable.create(), fromIterable(), etc. ! Retrofitting existing object-oriented design into Observable data streams can be messy ! Many, many open-source projects that wrap other implementations into an Rx package (an easy way to get ⭐ ⭐ ⭐ on GitHub) ! github.com/zsoltk/RxAndroidLibs - 500 stars for a list of libraries
  17. ~80 % Percent of the most popular languages are imperative

    
 or multi-paradigmatic languages Source: StackOverflow Developer Survey 2018
  18. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future
  19. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary
  20. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary ◦ Dialects
  21. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary ◦ Dialects ! Languages are multi-faceted and evolve over time. They are often multi- paradigmatic languages.
  22. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary ◦ Dialects ! Languages are multi-faceted and evolve over time. They are often multi- paradigmatic languages. ! Examples
  23. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary ◦ Dialects ! Languages are multi-faceted and evolve over time. They are often multi- paradigmatic languages. ! Examples ◦ Imperative (what you’re probably used to)
  24. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary ◦ Dialects ! Languages are multi-faceted and evolve over time. They are often multi- paradigmatic languages. ! Examples ◦ Imperative (what you’re probably used to) ◦ Reactive Programming (what we’re talking about today)
  25. What's a language paradigm? ! Computer languages resemble linguistic language

    ◦ Grammatical structures ◦ Tenses: past, present, future ◦ Vocabulary ◦ Dialects ! Languages are multi-faceted and evolve over time. They are often multi- paradigmatic languages. ! Examples ◦ Imperative (what you’re probably used to) ◦ Reactive Programming (what we’re talking about today) ◦ Functional Programming (used in Reactive Programming)
  26. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program
  27. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance
  28. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve
  29. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java
  30. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java if (value % 2 == 0) { // do something }
  31. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming if (value % 2 == 0) { // do something }
  32. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming ! Describes what the program should accomplish if (value % 2 == 0) { // do something }
  33. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming ! Describes what the program should accomplish ! Ideally stateless if (value % 2 == 0) { // do something }
  34. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming ! Describes what the program should accomplish ! Ideally stateless ! Evaluate functions and create expressions instead of statements if (value % 2 == 0) { // do something }
  35. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming ! Describes what the program should accomplish ! Ideally stateless ! Evaluate functions and create expressions instead of statements ! More difficult conceptually if (value % 2 == 0) { // do something }
  36. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming ! Describes what the program should accomplish ! Ideally stateless ! Evaluate functions and create expressions instead of statements ! More difficult conceptually ! Examples: Scala, Haskell if (value % 2 == 0) { // do something }
  37. Imperative vs. Functional Imperative Programming ! Describes how the program

    operates ! Uses statements to change state of the program ! Conditional statements, loops, inheritance ! Easier initial learning curve ! Examples: C, PHP, Java Functional Programming ! Describes what the program should accomplish ! Ideally stateless ! Evaluate functions and create expressions instead of statements ! More difficult conceptually ! Examples: Scala, Haskell if (value % 2 == 0) { // do something } boolean filter(int value) { return value % 2 == 0; }
  38. History of Imperative Programming ! Old computers utilized vacuum tubes

    and very limited memory ! Programs written as step-by-step instructions ! FORTRAN introduced in 1954. Compiled, variables, complex expressions. ! 60s and 70s: COBOL, BASIC, C ! Object-oriented code grew in popularity in the 1980s. Smalltalk. C++ ! 90s: Perl, Python, Javascript, Ruby, Java
  39. History of Functional Programming ! Based on lambda calculus (Church

    1936) ◦ Study of computation with functions ! Lisp was developed by IBM in the 1950s ◦ LISP = LISt Processor ◦ Still in use today ◦ Only a year younger than FORTRAN ! John Backus gave a 1978 Turing Award lecture on why imperative programming is “bad” and functional programming is “good” ! 80s-00s - Object-Oriented programming dominated based on principles like encapsulation. Academics and theoreticians care about Functional Programming. ! 2010s - JavaScript made passing around functions cool again
  40. A flow of data objects from one function to the

    next Reactive Programming
 1. Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  41. ! Functions are meant to be pure Reactive Programming
 1.

    Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  42. ! Functions are meant to be pure ! All functions

    have an input and output data types Reactive Programming
 1. Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  43. ! Functions are meant to be pure ! All functions

    have an input and output data types ! No external state is modified (no side-effects) Reactive Programming
 1. Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  44. ! Functions are meant to be pure ! All functions

    have an input and output data types ! No external state is modified (no side-effects) Example:
 add(x, y) -> return x + y Reactive Programming
 1. Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  45. Uses the Observer pattern with Subject data sources that notify

    Observers Reactive Programming
 1. Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  46. Uses the Observer pattern with Subject data sources that notify

    Observers Errors propagated through the flow of data Reactive Programming
 1. Data streams
 
 2. Functional programming
 
 3. Asynchronous observers

  47. RxJava ! The Java library for the Reactive Extensions specification

    ◦ This specification is applied to other languages: RxJs, RxSwift, etc. - reactivex.io/languages
  48. RxJava ! The Java library for the Reactive Extensions specification

    ◦ This specification is applied to other languages: RxJs, RxSwift, etc. - reactivex.io/languages ! Helpful due to complicated stream and asynchronous apis
  49. RxJava ! The Java library for the Reactive Extensions specification

    ◦ This specification is applied to other languages: RxJs, RxSwift, etc. - reactivex.io/languages ! Helpful due to complicated stream and asynchronous apis ! Brings functional design to an object-oriented language
  50. RxJava ! The Java library for the Reactive Extensions specification

    ◦ This specification is applied to other languages: RxJs, RxSwift, etc. - reactivex.io/languages ! Helpful due to complicated stream and asynchronous apis ! Brings functional design to an object-oriented language ! Very helpful for mobile development, which often involves asynchronously requesting data from a server, transforming it, and displaying it in the UI
  51. ... to subscribe to data Imperative List<Integer> data = 


    new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  52. ... to subscribe to data Imperative List<Integer> data = 


    new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  53. ... to subscribe to data Imperative List<Integer> data = 


    new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  54. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe(new Consumer<Integer>()

    { @Override public void accept(Integer value) { System.out.println(value); } }); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  55. ... to subscribe to data Imperative List<Integer> data = 


    new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Reactive new DataSource().getDataStream() .subscribe(new Consumer<Integer>() { @Override public void accept(Integer value) { System.out.println(value); } }); Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  56. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe(new Consumer<Integer>()

    { @Override public void accept(Integer value) { System.out.println(value); } }); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  57. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe(new Consumer<Integer>()

    { @Override public void accept(Integer value) { System.out.println(value); } }); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  58. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe(new Consumer<Integer>()

    { @Override public void accept(Integer value) { System.out.println(value); } }); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  59. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe(new Consumer<Integer>()

    { @Override public void accept(Integer value) { System.out.println(value); } }); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  60. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe(
 value

    -> System.out.println(value)
 ); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  61. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe( value

    -> System.out.println(value) ); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { System.out.println(value); } Output: 4, 2, 1, 7, 6, ... Data: 4, 2, 1, 7, 6, ...
  62. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe( value

    -> updateUI(value) ); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { updateUI(value); }
  63. ... to subscribe to data Reactive new DataSource().getDataStream() .subscribe( value

    -> saveToDatabase(value) ); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { saveToDatabase(value); }
  64. ... to subscribe to data changes Imperative ScheduledExecutorService scheduler =

    // initialize Runnable runner = new Runnable() { public void run() { List<Integer> data = new DataSource().getData(); for (Integer value : data) { System.out.println(value); } } }; ScheduledFuture<?> future = // initialize scheduler.schedule(new Runnable() { public void run() { future.cancel(/* mayInterruptIfRunning */ true); } }, /* delay */ 0, TimeUnit.SECONDS);
  65. ... to subscribe to data changes Imperative ScheduledExecutorService scheduler =

    // initialize Runnable runner = new Runnable() { public void run() { List<Integer> data = new DataSource().getData(); for (Integer value : data) { System.out.println(value); } } }; ScheduledFuture<?> future = // initialize scheduler.schedule(new Runnable() { public void run() { future.cancel(/* mayInterruptIfRunning */ true); } }, /* delay */ 0, TimeUnit.SECONDS); ???
  66. ... to subscribe to data changes Imperative ScheduledExecutorService scheduler =

    // initialize Runnable runner = new Runnable() { public void run() { List<Integer> data = new DataSource().getData(); for (Integer value : data) { System.out.println(value); } } }; ScheduledFuture<?> future = // initialize scheduler.schedule(new Runnable() { public void run() { future.cancel(/* mayInterruptIfRunning */ true); } }, /* delay */ 0, TimeUnit.SECONDS); Reactive new DataSource().getDataStream() .subscribe( value -> System.out.println(value) );
  67. ... to filter our data Imperative List<Integer> data = 


    new DataSource().getData(); for (Integer value : data) { if (value % 2 == 0) { System.out.println(value); } } Output: 4, 2, 6, ... Data: 4, 2, 1, 7, 6, ...
  68. ... to filter our data Imperative List<Integer> data = 


    new DataSource().getData(); for (Integer value : data) { if (value % 2 == 0) { System.out.println(value); } } Output: 4, 2, 6, ... Data: 4, 2, 1, 7, 6, ...
  69. ... to filter our data Reactive new DataSource().getDataStream() .filter(value ->

    value % 2 == 0) .subscribe(
 result -> System.out.println(result)
 ); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { if (value % 2 == 0) { System.out.println(value); } } Output: 4, 2, 6, ... Data: 4, 2, 1, 7, 6, ...
  70. ... to filter our data Reactive new DataSource().getDataStream() .filter(value ->

    value % 2 == 0) .subscribe(
 result -> System.out.println(result)
 ); Imperative List<Integer> data = 
 new DataSource().getData(); for (Integer value : data) { if (value % 2 == 0) { System.out.println(value); } } Output: 4, 2, 6, ... Data: 4, 2, 1, 7, 6, ...
  71. … to map our data Output: 8, 4, 2, 14,

    12, ... Data: 4, 2, 1, 7, 6, ...
  72. … to map our data Imperative List<Integer> data = new

    DataSource().getData(); for (Integer value : data) { int result = value * 2; System.out.println(result); } Output: 8, 4, 2, 14, 12, ... Data: 4, 2, 1, 7, 6, ...
  73. ... to map our data Imperative List<Integer> data = new

    DataSource().getData(); for (Integer value : data) { int result = value * 2; System.out.println(result); } Output: 8, 4, 2, 14, 12, ... Data: 4, 2, 1, 7, 6, ...
  74. ... to map our data Reactive new DataSource().getDataStream() .map(value ->

    value * 2) .subscribe( result -> System.out.println(result) ); Imperative List<Integer> data = new DataSource().getData(); for (Integer value : data) { int result = value * 2; System.out.println(result); } Output: 8, 4, 2, 14, 12, ... Data: 4, 2, 1, 7, 6, ...
  75. ... to map our data Reactive new DataSource().getDataStream() .map(value ->

    value * 2) .subscribe( result -> System.out.println(result) ); Imperative List<Integer> data = new DataSource().getData(); for (Integer value : data) { int result = value * 2; System.out.println(result); } Output: 8, 4, 2, 14, 12, ... Data: 4, 2, 1, 7, 6, ...
  76. ... to group our data List<Integer> data = new DataSource().getData();

    Map<String, List<Integer>> result = new HashMap<>(); String evenKey = "EVEN"; String oddKey = "ODD"; for (Integer value : data) { String key; if (value % 2 == 0) { key = evenKey; } else { key = oddKey; } result.putIfAbsent( key, new ArrayList<>()); result.get(key).add(datum); } System.out.println(result); Output: {EVEN=[4, 2, 6], ODD=[1, 7]} Data: 4, 2, 1, 7, 6
  77. ... to group our data new DataSource().getDataStream() .groupBy( value ->

    (value % 2) == 0 ? "EVEN" : "ODD" ) .collectInto( // put our groups into a hashmap // this is actually still a little messy ) .subscribe( resultMap -> System.out.println(resultMap) ); Output: {EVEN=[4, 2, 6], ODD=[1, 7]} Data: 4, 2, 1, 7, 6
  78. ... to group our data new DataSource().getDataStream() .groupBy( value ->

    (value % 2) == 0 ? "EVEN" : "ODD" ) .collectInto( // put our groups into a hashmap // this is actually still a little messy ) .subscribe( resultMap -> System.out.println(resultMap) ); List<Integer> data = new DataSource().getData(); Map<String, List<Integer>> result = new HashMap<>(); String evenKey = "EVEN"; String oddKey = "ODD"; for (Integer value : data) { String key; if (value % 2 == 0) { key = evenKey; } else { key = oddKey; } result.putIfAbsent( key, new ArrayList<>()); result.get(key).add(datum); } System.out.println(result); Output: {EVEN=[4, 2, 6], ODD=[1, 7]} Data: 4, 2, 1, 7, 6
  79. So many more operators ! Transforming ! Buffer ! Scan

    ! Filtering ! Debounce ! Distinct ! First ! Last ! Take ! Min ! Combining ! Join ! Merge ! Zip ! Math ! Average ! Concat ! Max