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

Why Reactive Programming?

Why Reactive Programming?

An introduction to Reactive Programming focused on Android.
The sample codes are written in RxJava with Kotlin.

Slides at Android Dev Conference BR 2017.

Felipe Costa

August 25, 2017
Tweet

More Decks by Felipe Costa

Other Decks in Programming

Transcript

  1. Why Reactive Programming? Felipe Costa Android Developer @ OLX Brasil

    Bruno Kosawa Android Developer @ OLX Brasil
  2. OLX is part of the biggest online marketplace group in

    the world Why Reactive Programming? About OLX Brasil One of the biggest groups on Internet1 One of the biggest groups of online classified2 1 USDbn mkt cap, Fev/2017 2 EURm receita classificados, 2015
  3. OLX is the result of two big companies Why Reactive

    Programming? About OLX Brasil 50% 50% + = Shareholders
  4. Why Reactive Programming? About the Speakers • Bacharel em Ciência

    da Computação pela UFRJ • Trabalha com programação desde 2011 • Trabalha com Android desde 2014 • Engenheiro de software na OLX há 1 ano • Bacharel em Ciência da Computação pela UFRJ • Trabalha com programação desde 2010 • Trabalha com Android desde 2011 • Engenheiro de software na OLX há 2 anos Felipe Costa Bruno Kosawa
  5. Counter function fun count(array: Array<String>): Int {
 var count =

    0
 
 for (item in array)
 count++
 
 return count
 } Why Reactive Programming? 1. Input and Output
  6. Kinds of inputs we deal with Why Reactive Programming? //

    Listeners
 View.OnClickListener { view -> /* */ } // Lifecycle Callbacks
 override fun onCreate(savedInstanceState: Bundle?) { /* */ }
 override fun onBindViewHolder(holder: ViewHolder, position: Int) { /* */ }
 
 // Async Callbacks
 override fun onFailure(throwable: Throwable) { /* */ }
 override fun onResponse(response: ReponseDTO) { /* */ } 1. Input and Output
  7. Why Reactive Programming? 1. Input and Output override fun onCreate(savedInstanceState:

    Bundle?, persistentState: PersistableBundle?) {
 super.onCreate(savedInstanceState, persistentState)
 
 setupInitialState()
 
 Api.loadCharacters(object : ResponseCallback<List<Character>> {
 
 override fun onResponse(response: List<Character>) {
 updateUI(response)
 }
 
 override fun onFailure(throwable: Throwable) {
 showLoadCharactersError()
 }
 })
 
 button.setOnClickListener {
 
 Api.favoriteCharacter(object : ResponseCallback<Character> {
 
 override fun onResponse(response: Character) {
 updateFavoriteUI(response)
 }
 
 override fun onFailure(throwable: Throwable) {
 handleFavoriteError()
 }
 })
 }
 } Execution Order Framework Network Network UI Time
  8. Imperative Programming Why Reactive Programming? 1. Input and Output Framework

    Network UI Others Execution Order Time Update State Know what happened previously
  9. State is exponentially complex Why Reactive Programming? val isDisplayed: Boolean

    // 2 states
 
 val isEnabled: Boolean // 4 states
 
 val isSelected: Boolean // 8 states
 
 val isFavored: Boolean // 16 states 1. Input and Output
  10. Why Reactive Programming? 1. Input and Output Compositional Event System

    (Non-Linear Programming) Imperative Programming
  11. • Paper 1989 - Gérard Berry • Microsoft Rx (2009)

    • Rx = Reactive Extensions • RxJava (Kotlin S2) • “Functional Reactive Programming” A little bit of context Why Reactive Programming? 2. Definition
  12. We all responde to flowing data and react to changes…

    Broadcasts Why Reactive Programming? 2. Definition Listeners MVP MVC Callbacks Event Bus
  13. What is reactive programming? It is programming paradigm oriented by

    data streams and the propagation of change Why Reactive Programming? 2. Definition
  14. Propagation of Change Having α := ß + γ with

    ß = 10 and γ = 20 Why Reactive Programming? 3. Propagation of change Spreadsheet ß γ α 10 20 30
  15. Propagation of Change When ß changes to 30, α changes

    as well Why Reactive Programming? 3. Propagation of change Spreadsheet ß γ α 30 20 50
  16. Observer Pattern Why Reactive Programming? 3. Propagation of change Observer

    +notify() ConcreteObserver2 +notify() ConcreteObserver1 +notify() Subject +registerObserver(observer) +unregisterObserver(observer) +notifyObservers() +observerCollection
  17. Observable Why Reactive Programming? 3. Propagation of change • Container

    that can be emit signals to observers • Signals are emitted through time
  18. Data Stream Values over time. Examples: • Mouse cursor positions

    on the screen; • Property values updates; • Text Field changes; • Bits being downloaded from the cloud Why Reactive Programming? 4. Data streams
  19. Why Reactive Programming? 4. Data streams just("Alpha", "Beta", "Gamma") .subscribe({

    it -> println(it)}, { println("completed")}) Time Gamma Beta Alpha onCompleted
  20. Why Reactive Programming? 4. Data streams just("Alpha", "Beta", "Gamma") .subscribe({

    it -> println(it)}, { it -> println(it.message)}, { println("completed")}) Time Gamma Beta Alpha onError
  21. Time Why Reactive Programming? 5. Data streams are composable Time

    Observable.transform(f: (x) -> y): Observable
  22. Why Reactive Programming? 5. Data streams are composable var lastClickTime:

    Long = 0 override fun onClick(v: View) { val clickTime = System.currentTimeMillis() if (clickTime - lastClickTime < 700L) { onDoubleClick(v) lastClickTime = 0 } else { onSingleClick(v) } lastClickTime = clickTime } fun onSingleClick(v: View) { /* */ } fun onDoubleClick(v: View) { /* */ } Double Tap
  23. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .map { if (it == 2) "Double Tap" else "" } .subscribe(textView::setText) Double Tap
  24. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .map { if (it == 2) "Double Tap" else "" } .subscribe(textView::setText) Double Tap Time
  25. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .map { if (it == 2) "Double Tap" else "" } .subscribe(textView::setText) Double Tap Time Time Buffer(700L)
  26. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .map { if (it == 2) "Double Tap" else "" } .subscribe(textView::setText) Double Tap Time Time Map { it.size } 1 2 1 3
  27. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .map { if (it == 2) "Double Tap" else "" } .subscribe(textView::setText) Double Tap Time Time map { if (it == 2) "Double Tap" else "" } DT 1 2 1 3
  28. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .map { if (it == 2) "Double Tap" else "" } .subscribe(textView::setText) Double Tap
  29. Why Reactive Programming? 5. Data streams are composable container.clicks() .buffer(700L,

    TimeUnit.MILLISECONDS) .map { it.size } .filter { it >= 2 } Multiple Tap
  30. Why Reactive Programming? 5. Data streams are composable var counter

    = 0 upButton.setOnClickListener { counter++ resultTextView.text = counter.toString() } downButton.setOnClickListener { counter-- resultTextView.text = counter.toString() } Up and Down
  31. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  32. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  33. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  34. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  35. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  36. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  37. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  38. Why Reactive Programming? 5. Data streams are composable val upStream

    = upButton.clicks().map { 1 } val downStream = downButton.clicks().map { -1 } merge(upStream, downStream) .startWith(0) .scan({ t1, t2 -> t1 + t2 }) .map { it.toString() } .subscribe(resultTextView::setText) Up and Down
  39. fun callbackHellExample() {
 favoriteButton.setOnClickListener(View.OnClickListener {
 Api.favoriteCharacter(!character.isFavorite, object : Callback<Boolean> {


    override fun success(isFavorite: Boolean) {
 }
 
 override fun error(throwable: Throwable) {
 showMessage("Error: " + throwable.message)
 }
 })
 })
 } Why Reactive Programming? 5. Data streams are composable
  40. fun callbackHellExample() {
 favoriteButton.setOnClickListener(View.OnClickListener {
 Api.favoriteCharacter(!character.isFavorite, object : Callback<Boolean> {


    override fun success(isFavorite: Boolean) {
 character.save(isFavorite, object : Callback<Character> {
 
 })
 }
 
 override fun error(throwable: Throwable) {
 showMessage("Error: " + throwable.message)
 }
 })
 })
 } Why Reactive Programming? 5. Data streams are composable
  41. fun callbackHellExample() {
 favoriteButton.setOnClickListener(View.OnClickListener {
 Api.favoriteCharacter(!character.isFavorite, object : Callback<Boolean> {


    override fun success(isFavorite: Boolean) {
 character.save(isFavorite, object : Callback<Character> {
 override fun success(character: Character) {
 updateUI(character)
 }
 
 override fun error(otherThrowable: Throwable) {
 showMessage("Error: " + otherThrowable.message)
 }
 })
 }
 
 override fun error(throwable: Throwable) {
 showMessage("Error: " + throwable.message)
 }
 })
 })
 } Why Reactive Programming? 5. Data streams are composable
  42. Why Reactive Programming? 5. Data streams are composable fun reactiveExample()

    { favoriteButton.clicks() .flatMap { Api.favorite(!character.isFavorite) } }
  43. Why Reactive Programming? 5. Data streams are composable fun reactiveExample()

    { favoriteButton.clicks() .flatMap { Api.favorite(!character.isFavorite) } .flatMap { isFavorite: Boolean -> character.save(isFavorite) } }
  44. Why Reactive Programming? 5. Data streams are composable fun reactiveExample()

    { favoriteButton.clicks() .flatMap { Api.favorite(!character.isFavorite) } .flatMap { isFavorite: Boolean -> character.save(isFavorite) } .doOnError { error: Throwable -> showMessage("Error: {error.message}") } }
  45. Why Reactive Programming? 5. Data streams are composable fun reactiveExample()

    { favoriteButton.clicks() .flatMap { Api.favorite(!character.isFavorite) } .flatMap { isFavorite: Boolean -> character.save(isFavorite) } .doOnError { error: Throwable -> showMessage("Error: {error.message}") } .subscribe { character: Character -> updateUI(character) } }
  46. Why Reactive Programming? 6. Concurrency fun reactiveExample() { favoriteButton.clicks() .flatMap

    { Api.favorite(!character.isFavorite) } .flatMap { isFavorite: Boolean -> character.save(isFavorite) } .doOnError { error: Throwable -> showMessage("Error: {error.message}") } .subscribe { character: Character -> updateUI(character) } }
  47. Why Reactive Programming? 6. Concurrency fun reactiveExample() { favoriteButton.clicks() .flatMap

    { Api.favorite(!character.isFavorite) } .flatMap { isFavorite: Boolean -> character.save(isFavorite) } .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .doOnError { error: Throwable -> showMessage("Error: {error.message}") } .subscribe { character: Character -> updateUI(character) } }
  48. • http://reactivex.io • https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 • http://blog.danlew.net/2017/07/27/an-introduction-to-functional- reactive-programming/ • http://joshaber.github.io/2013/02/11/input-and-output/ •

    https://github.com/felipehjcosta/kotlin-rxjava-android • https://github.com/felipehjcosta/reactive-programming-samples Links Why Reactive Programming? 7. Conclusion