KEMBAR78
Reactive programming | PDF
Reactive programming
Introduction to ReactiveX API
Jianbin LIN
jianbin.lin@live.com
ReactiveX
• An API for asynchronous programming with
observable streams
Ready ?
Start with some quizzes !
Usage of constant
Let result be 3 times of a
let a = 36
result = ?
result = 3 * a
108
var a = 36
Let result be 3 times of a
Usage of variable
result = ?
108
Usage of variable
result = 3 * a
Why ?
The value of a variable varies
over time.
The value of a variable varies
over time.
Variable is NOT one
value, but a stream of
values
36
94
8
19
a
t
Initial value
Current value
result <- a * 3
result is 108
or 57 ?
108
282
24
57
result
t
Initial value
Current value
36
94
8
19
a
t
Initial value
Current value
Better ways to use variable
- ask repeatedly 

- consume too much system resources

- Annoying !
- call me when there is update

- 1 to many, easy to scale
Poll
Push
Observer pattern
Observer pattern
Reactive
What is an Observable ?
- A stream that emits values
- Observer can subscribe to it
& react to the value it emits
The reactive way of using a
variable
onNext: { (newValue)
result = newValue * 3
})
Reactive
variable type
Create the subject
Let observer subscribe
on it
Callback when a is
updated
let a = Variable(36)
a.subscribe(
What can be emitted from a
Observable stream ?
Any value
Integer
Double
Network request response
Other custom object
User event
click
Swipe
Keyboard input
Voice input
System event
Low memory notification
function call
remote push notification
Questions ?
Observable also emits 2 special events
Error
Completion
Register call back on error & completion
observableClick.subscribe(onNext: {
(newClick)
// handle the click
},
onError: {
(error)
// handle the error
},
onCompletion: {
// do something when observable is completed
})
Timing & Threading
call-backs happens when & where ?
By default, synchronous
- callbacks run immediately (blocking)
- on whichever thread elements are
generated
By default, synchronous
a.subscribe(onNext: {
(newValue) in
result = newValue * 3
})
a.value = 97
Thread A
Thread B
Asynchronous: by scheduler
- callbacks run asynchronously
- on the thread chosen on subscription
Asynchronous: by scheduler
anObservable
.observeOn(UIScheduler.instance)
.subscribe(onNext: {
result = newValue * 3
})
a.value = 97
Thread A
Thread B
Schedulers
• Serial Dispatch Queue Scheduler
• Concurrent Dispatch Queue Scheduler
• MainScheduler (Serial scheduler)
OR
Implement your own
synchronous/asynchronous
scheduler
Combine observable
Why this is great ?
- Save us from the control flow hell

- Reveal the clear dependency
Sum = ?
<- input x
<- input y
<- input z
func updateResult() {
run_on_ui_thread{
sum <- x + y + z
display(sum)
}
}
var x = 1
var y = 2
var z = 3
Imperative way
func setX(value){
x = value
updateResult()
}
func setY(value){
y = value
updateResult()
}
func setZ(value){
z = value
updateResult()
}
Imperative way
combineLatest(x, y, z)
.observeOn(UIScheduler.instance)
.subscribe({
sum = xValue + yValue + zValue
display(sum)
}
Reactive wayx = Variable(1)
y = Variable(2)
z = Variable(3)
One clear dependency
No complex control flow
Not bad !
But just toy problem
Questions ?
More practical problem
Loading….
Better to have only one
class Spinner{
public var enabled: Bool
}
let spinner = Spinner()
spinner.enabled = true
spinner.enabled = false
class Request {
fun makeRequest(callback: Closure)
}
Request A
Page loaded
spinner.enabled = true spinner.enabled = false
t
Request A
Page loaded
spinner.enabled = true spinner.enabled = false
Request B
spinner.enabled = true spinner.enabled = false
t
t
Request A
Page loaded
Request B
t
Request C
What are the causes of the
problem ?
No explicit states
Requests cannot know the states of
each other.

class Request {
fun makeRequest(callback: Closure)
}
Encapsulation is violated
Request A
spinner.enabled = true spinner.enabled = false
t
Encapsulation
- Encapsulation is the important
Encapsulation is violated
Request A
spinner.enabled = true spinner.enabled = false
t
- All requests are trying to control the spinner

- Spinner is not autonomic
Solution
Define explicit states for requests

class Request {
let isLoading: Variable(Bool) = false
fun makeRequest(completion: CallBack)
}
Request A
Page loaded
self.isLoading = true self.isLoading = false
Request B
self.isLoading = true self.isLoading = false
t
t
Don’t modify spinner state directly
Solution
let spinner itself decide what to do

class Spinner{
private var enabled: Bool
func setUp(){
combineLatest(requestA.isLoading,
requestB.isLoading,
requestC.isLoading)
.observeOn(UIScheduler.instance)
.subscribe({
self.enabled =
requestA.isLoading || requestB.isLoading ||
requestC.isLoading
})
}
Pretty good, what else ?
Observable = stream = sequence of values
Does it remind you something ?
Functional programming
Filter
anObservable
.filter{$0 > 10}
.subscribe(onNext: {
// handle filtered value
})
Debounce
textObservable
.debounce(0.2)
.subscribe(onNext: {
// handle value
})
Map
anObservable
.map{return $0 * 10}
.subscribe(onNext: {
// handle filtered value
})
Why Rx ?
• Encourage to code with explicit states
• Code: less, easier to reason about
• Free error handling infrastructure
• Less complex threading
• Make object more autonomic
Drawbacks of Rx
• Hard to trace the source of change
• Dependency cycle
• Deadlock/memory leak
My suggestions
• Using Rx wisely can simplify your life
• Use Rx with good architecture in mind
• The goal is to improve code readability NOT to crash it
• Don’t try to do everything in one function
Questions ?
What would happen if we put stream into stream ?

Reactive programming