Why Reactive Programming?
Felipe Costa
Android Developer @ OLX Brasil
Bruno Kosawa
Android Developer @ OLX Brasil
Slide 2
Slide 2 text
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
Slide 3
Slide 3 text
OLX is the result of two big companies
Why Reactive Programming?
About OLX Brasil
50% 50%
+ =
Shareholders
Slide 4
Slide 4 text
Why Reactive Programming?
About OLX Brasil
Sources: Fabric
0.5 M
DAU
3 M
DAU
Slide 5
Slide 5 text
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
Slide 6
Slide 6 text
1Why Reactive Programming?
Input and Output
Slide 7
Slide 7 text
"Programs take input and produce
output."
Slide 8
Slide 8 text
Counter function
fun count(array: Array): Int {
var count = 0
for (item in array)
count++
return count
}
Why Reactive Programming?
1. Input and Output
Slide 9
Slide 9 text
Unix tool
Why Reactive Programming?
1. Input and Output
Slide 10
Slide 10 text
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
Slide 11
Slide 11 text
Why Reactive Programming?
1. Input and Output
Imperative Programming
Slide 12
Slide 12 text
Why Reactive Programming?
1. Input and Output
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
super.onCreate(savedInstanceState, persistentState)
setupInitialState()
Api.loadCharacters(object : ResponseCallback> {
override fun onResponse(response: List) {
updateUI(response)
}
override fun onFailure(throwable: Throwable) {
showLoadCharactersError()
}
})
button.setOnClickListener {
Api.favoriteCharacter(object : ResponseCallback {
override fun onResponse(response: Character) {
updateFavoriteUI(response)
}
override fun onFailure(throwable: Throwable) {
handleFavoriteError()
}
})
}
}
Execution
Order
Framework Network Network
UI
Time
Slide 13
Slide 13 text
Imperative Programming
Why Reactive Programming?
1. Input and Output
Framework
Network
UI
Others
Execution
Order
Time
Update State
Know what happened
previously
Slide 14
Slide 14 text
State
Slide 15
Slide 15 text
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
Slide 16
Slide 16 text
Why Reactive Programming?
1. Input and Output
Compositional Event System
(Non-Linear Programming)
Imperative Programming
Slide 17
Slide 17 text
Why Reactive Programming?
1. Input and Output
Reactive Programming
Slide 18
Slide 18 text
Why Reactive Programming?
1. Input and Output
Reactive Programming
Slide 19
Slide 19 text
2Why Reactive Programming?
Definition
Slide 20
Slide 20 text
• 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
Slide 21
Slide 21 text
"Reactive programming is
programming with asynchronous
data streams."
Slide 22
Slide 22 text
We all responde to flowing
data and react to changes… Broadcasts
Why Reactive Programming?
2. Definition
Listeners
MVP
MVC
Callbacks Event
Bus
Slide 23
Slide 23 text
What is reactive programming?
It is programming paradigm oriented by data streams and the
propagation of change
Why Reactive Programming?
2. Definition
Slide 24
Slide 24 text
3Why Reactive Programming?
Propagation of change
Slide 25
Slide 25 text
Propagation of Change
Having
α := ß + γ
with
ß = 10
and
γ = 20
Why Reactive Programming?
3. Propagation of change
Spreadsheet
ß γ α
10 20 30
Slide 26
Slide 26 text
Propagation of Change
When ß changes to 30, α changes as
well
Why Reactive Programming?
3. Propagation of change
Spreadsheet
ß γ α
30 20 50
Why Reactive Programming?
3. Propagation of change
Observable
Slide 32
Slide 32 text
Observable
Why Reactive Programming?
3. Propagation of change
• Container that can be emit signals to observers
• Signals are emitted through time
Slide 33
Slide 33 text
4Why Reactive Programming?
Data streams
Slide 34
Slide 34 text
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
Slide 35
Slide 35 text
Why Reactive Programming?
4. Data streams
Observable.just("Alpha", "Beta", "Gamma")
Time
Slide 36
Slide 36 text
Why Reactive Programming?
4. Data streams
just("Alpha", "Beta", "Gamma").subscribe()
Time
Gamma
Beta
Alpha
Slide 37
Slide 37 text
Why Reactive Programming?
4. Data streams
just("Alpha", "Beta", "Gamma").subscribe({ it -> println(it)})
Time
Gamma
Beta
Alpha
Slide 38
Slide 38 text
Why Reactive Programming?
4. Data streams
just("Alpha", "Beta", "Gamma")
.subscribe({ it -> println(it)},
{ println("completed")})
Time
Gamma
Beta
Alpha onCompleted
Slide 39
Slide 39 text
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
Slide 40
Slide 40 text
5Why Reactive Programming?
Data streams are composable
Slide 41
Slide 41 text
Time
Why Reactive Programming?
5. Data streams are composable
Time
Observable.transform(f: (x) -> y): Observable
Slide 42
Slide 42 text
Time
Why Reactive Programming?
5. Data streams are composable
5
2 8
1
Time 2 16
4 10
map { it * 2 }
Slide 43
Slide 43 text
Time
Why Reactive Programming?
5. Data streams are composable
5
2 8
1
Time 8
2
filter { it % 2 == 0 }
Slide 44
Slide 44 text
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
Slide 45
Slide 45 text
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
Slide 46
Slide 46 text
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
Slide 47
Slide 47 text
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)
Slide 48
Slide 48 text
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
Slide 49
Slide 49 text
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
Slide 50
Slide 50 text
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
Slide 51
Slide 51 text
Why Reactive Programming?
5. Data streams are composable
container.clicks()
.buffer(700L, TimeUnit.MILLISECONDS)
.map { it.size }
.filter { it >= 2 }
Multiple Tap
Slide 52
Slide 52 text
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
Slide 53
Slide 53 text
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
Slide 54
Slide 54 text
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
Slide 55
Slide 55 text
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
Slide 56
Slide 56 text
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
Slide 57
Slide 57 text
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
Slide 58
Slide 58 text
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
Slide 59
Slide 59 text
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
Slide 60
Slide 60 text
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
Slide 61
Slide 61 text
fun callbackHellExample() {
favoriteButton.setOnClickListener(View.OnClickListener {
})
}
Why Reactive Programming?
5. Data streams are composable
Slide 62
Slide 62 text
fun callbackHellExample() {
favoriteButton.setOnClickListener(View.OnClickListener {
Api.favoriteCharacter(!character.isFavorite, object : Callback {
override fun success(isFavorite: Boolean) {
}
override fun error(throwable: Throwable) {
showMessage("Error: " + throwable.message)
}
})
})
}
Why Reactive Programming?
5. Data streams are composable
Slide 63
Slide 63 text
fun callbackHellExample() {
favoriteButton.setOnClickListener(View.OnClickListener {
Api.favoriteCharacter(!character.isFavorite, object : Callback {
override fun success(isFavorite: Boolean) {
character.save(isFavorite, object : Callback {
})
}
override fun error(throwable: Throwable) {
showMessage("Error: " + throwable.message)
}
})
})
}
Why Reactive Programming?
5. Data streams are composable
Slide 64
Slide 64 text
fun callbackHellExample() {
favoriteButton.setOnClickListener(View.OnClickListener {
Api.favoriteCharacter(!character.isFavorite, object : Callback {
override fun success(isFavorite: Boolean) {
character.save(isFavorite, object : Callback {
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
Slide 65
Slide 65 text
Why Reactive Programming?
5. Data streams are composable
fun reactiveExample() {
favoriteButton.clicks()
}
Slide 66
Slide 66 text
Why Reactive Programming?
5. Data streams are composable
fun reactiveExample() {
favoriteButton.clicks()
.flatMap { Api.favorite(!character.isFavorite) }
}
Slide 67
Slide 67 text
Why Reactive Programming?
5. Data streams are composable
fun reactiveExample() {
favoriteButton.clicks()
.flatMap { Api.favorite(!character.isFavorite) }
.flatMap { isFavorite: Boolean -> character.save(isFavorite) }
}