SlideShare a Scribd company logo
Kotlin Coroutine - the next step
for RxJava developer?
Artur Latoszewski
Agenda:
1. Pre-Kotlin world
2. What are coroutines and why we need it
3. Theoretical knowledge
4. Basic tutorial (some code)
5. Extra examples (more code)
6. Answer for the title question
7. Where to find more information
What have we had in pre-Kotlin world?
● AsyncTasks
● Threads
Painful points:
● Android Lifecycle
● Awful API
● Callbacks
● Easy to make a bug
● Hard to debug
● Concurrency is hard
What have we had in pre-Kotlin world? - RxJava!
http://reactivex.io/
We are Kotliners!
What are Coroutines for a developer?
Coroutines allows us to write asynchronous code in
sequential way.
fun loadData() {
var data = api.getData()
showData(data)
}
sequential code
(not coroutine)
What problem does it solve?
What problem does it solve? Callbacks!
https://www.twilio.com/blog/2017/03/promises-in-swift-writing-cleaner-asynchronous-code-using-promisekit.html
RxJava problems?
Observable.just(1,2,3,4)
.map { /*someMapping*/ }
.filter { /*someFilter*/ }
.subscribe(
{ /*onNext*/ },
{ /*onError*/ }
)
RxJava problems?
Observable.just(1,2,3,4)
.map { /*someMapping*/ }
.filter { /*someFilter*/ }
.subscribe(
{ /*onNext*/ },
{ /*onError*/ }
)
Callbacks
RxJava problems?
Observable.just(1,2,3,4)
.map { /*someMapping*/ }
.filter { /*someFilter*/ }
.subscribe(
{ /*onNext*/ },
{ /*onError*/ }
)
Callbacks
Stream style
Theoretical knowledge
Coroutines - deep dive
● conceptually very light-weight threads
● one thread = ∞ coroutines
● compiled to state machine with shared state (and callbacks)
● 100K Threads = 💔, 100K Coroutines = 💚
● less context switch overhead
● less memory overhead
● works everywhere where Kotlin works
● stable since Kotlin 1.3
Suspend function
● suspend and executed later
● without blocking thread
● without changing context
● almost free
suspend fun doWorld() {
println("World!")
}
Coroutine context = Job + Dispatcher
Job (Rx ~ CompositeDisposable)
● a cancellable thing
● can’t be reused after cancel
● parent-child hierarchies
● SupervisorJob - child don’t cancel parent
Dispatchers (Rx ~ Schedulers)
● Default - thread pool = CPU cores
● Main - run on main thread (main UI thread on Android)
● IO - designed for IO tasks, share with Default
● launch() - fire and forget
○ return Job object - allows to cancel coroutine
○ uncaught exceptions = crash
● async() - promise that it will return object
○ return Deferred<out T> : Job on which we call await() to wait for result
○ without await() call it will “swallow” exception
● runBlocking() - locks current thread until end of execution
● withContext() - run internal block on specified context
Coroutine builder
Kotlin coroutine - the next step for RxJava developer?
Coroutines - first
launch{
println("We are in coroutine")
}
Coroutines - first
val job = GlobalScope.launch(Dispatchers.Main){
println("We are in coroutine")
}
Coroutines - cancel
val job = GlobalScope.launch(Dispatchers.Main){
println("We are in coroutine")
}
job.cancel()
------------------------------------------------------------------
RxJava disposable.dispose()
Coroutines - cancel
val job = launch (Dispatchers.Main){
while (true){
println("We are in coroutine")
}
}
job.cancel()
Coroutines - cancel
val job = launch (Dispatchers.Main){
while (isActive){
println("We are in coroutine")
}
}
job.cancel()
------------------------------------------------------------------
RxJava isDisposed()
CoroutineScope
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
● every coroutine needs a scope (coroutine is extension method)
● scope is a lifecycle for a coroutine
● scopes creates “scope tree”
● you don’t want to use GlobalScope
CoroutineScope - Activty
class MyActivity : AppCompatActivity(), CoroutineScope {
lateinit var parentJob: SupervisorJob
override val coroutineContext: CoroutineContext = Dispatchers.Main + parentJob
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
parentJob = SupervisorJob()
}
override fun onDestroy() {
super.onDestroy()
parentJob.cancel()
}
}
CoroutineScope - Activty
class MyActivity : AppCompatActivity(), CoroutineScope {
override val coroutineContext: CoroutineContext = Dispatchers.Main + parentJob
fun buildCoroutineTree(){
launch { // MyActivity scope
async { // launch scope }
}
launch { // MyActivity scope }
}
override fun onDestroy() {
parentJob.cancel() // Cancel all coroutines in scope
}
}
CoroutineScope - ViewModel
class MyActivity : ViewModel(), CoroutineScope {
val parentJob = SupervisorJob()
override val coroutineContext: CoroutineContext = Dispatchers.Main + parentJob
override fun onCleared() {
super.onCleared()
parentJob.cancel()
}
fun doSomeStuff() {
launch{ // launch scope }
}
}
CoroutineScope - ViewModel
class MyActivity : ViewModel(), CoroutineScope {
fun doSomeStuff() {
viewModelScope.launch{ // launch scope }
}
}
● AndroidX Lifecycle v2.1.0 (alpha)
Coroutines - change context (thread)
launch (Dispatchers.Main){
println("Coroutine in main thread")
withContext(Dispatchers.IO){
println("Coroutine in background thread")
}
println("Coroutine in main thread")
}
------------------------------------------------------------------
RxJava
.observeOn()
.subscribeOn()
.unsubscribeOn()
Coroutines - sequentially
fun loadDataSequentially() {
launch(Dispatchers.Main) {
val response1 = withContext(Dispatchers.IO) { loadData1() } // 1
val response2 = withContext(Dispatchers.IO) { loadData2() } // 2
val result = response1 + response2 // 3
}
}
Coroutines - sequentially
fun loadDataSequentially() {
launch(Dispatchers.Main) {
val response1 = withContext(Dispatchers.IO) { loadData1() } // 1
val response2 = withContext(Dispatchers.IO) { loadData2() } // 2
val result = response1 + response2 // 3
}
}
Coroutines - asynchronous
launch(Dispatchers.Main) {
val response = async(Dispatchers.IO) { // Deferred<Response>
println("We are in async coroutine")
// doing stuff in background thread
loadData()
}
// doing stuff main thread
val value = response.await() // await for response
}
Coroutines - parallel
fun loadDataParallel() {
launch(Dispatchers.Main) {
val response1 = async(Dispatchers.IO) { loadData1() }
val response2 = async(Dispatchers.IO) { loadData2() }
// doing stuff main thread
val result = response1.await() + response1.await() //await for response
}
}
Coroutines - parallel
fun loadDataParallel() {
launch(Dispatchers.Main) {
val response1 = async(Dispatchers.IO) { loadData1() }
val response2 = async(Dispatchers.IO) { loadData2() }
// doing stuff main thread
val result = response1.await() + response1.await() //await for response
}
}
More complex examples
RxJava
vs
Coroutine
Dmytro Danylyk
@dmytrodanylyk
Android/Kotlin Google
Developer Expert
Operators?
Everything from Kotlin Collections (map, filter, etc.) and more:
fun loadDataWithTimeout() {
launch(Dispatchers.Main) {
val response = async(Dispatchers.IO) { loadData() }
val result = withTimeoutOrNull(2, TimeUnit.SECONDS) { response.await() }
}
Retry
suspend fun <T> retry(block: suspend (Int) -> T): T {
for (i in 1..5) { // try 5 times
try {
return withTimeout(500) { // with timeout
block(i)
}
} catch (e: TimeoutCancellationException) { /* retry */ }
}
return block(0) // last time just invoke without timeout
}
Retry
suspend fun <T> retry(block: suspend (Int) -> T): T {
for (i in 1..5) { // try 5 times
try {
return withTimeout(500) { // with timeout
block(i)
}
} catch (e: TimeoutCancellationException) { /* retry */ }
}
return block(0) // last time just invoke without timeout
}
Retry
suspend fun <T> retry(block: suspend (Int) -> T): T {
for (i in 1..5) { // try 5 times
try {
return withTimeout(500) { // with timeout
block(i)
}
} catch (e: TimeoutCancellationException) { /* retry */ }
}
return block(0) // last time just invoke without timeout
}
Retry
suspend fun <T> retry(block: suspend (Int) -> T): T {
for (i in 1..5) { // try 5 times
try {
return withTimeout(500) { // with timeout
block(i)
}
} catch (e: TimeoutCancellationException) { /* retry */ }
}
return block(0) // last time just invoke without timeout
}
Retry
suspend fun <T> retry(block: suspend (Int) -> T): T {
for (i in 1..5) { // try 5 times
try {
return withTimeout(500) { // with timeout
block(i)
}
} catch (e: TimeoutCancellationException) { /* retry */ }
}
return block(0) // last time just invoke without timeout
}
Retry
suspend fun <T> retry(block: suspend (Int) -> T): T {
for (i in 1..5) { // try 5 times
try {
return withTimeout(500) { // with timeout
block(i)
}
} catch (e: TimeoutCancellationException) { /* retry */ }
}
return block(0) // last time just invoke without timeout
}
Retrofit
interface RemoteDataSource{
@GET("api/news")
fun getNews() : Single<NewsResponse>
}
------------------------------------------------------------------
interface RemoteDataSource {
@GET("api/news")
fun getNews(): Deferred<NewsResponse>
}
------------------------------------------------------------------
interface RemoteDataSource {
@GET("api/news")
suspend fun getNews(): NewsResponse
}
RxJava
Adapter by
JakeWharton
Retrofit 2.5.1
Channels
● experimental
● hot observables in Rx world
● have buffer (default is 1)
● cold observables -
top issue
● cold observables ~
Sequences
val channel = Channel<Int>(1) // capacity 1
//Execution order
fun channelSend() = launch {
channel.send(1) //1
channel.send(1) //3
}
fun channelReceive() = launch {
val value1 = channel.receive() //2
val value2 = channel.receive() //4
}
Channels
● experimental
● hot observables in Rx world
● have buffer (default is 1)
● cold observables -
top issue
● cold observables ~
Sequences
val channel = Channel<Int>(1) // capacity 1
//Execution order
fun channelSend() = launch {
channel.send(1) //1
channel.send(1) //3
}
fun channelReceive() = launch {
val value1 = channel.receive() //2
val value2 = channel.receive() //4
}
Channels
● experimental
● hot observables in Rx world
● have buffer (default is 1)
● cold observables -
top issue
● cold observables ~
Sequences
val channel = Channel<Int>(1) // capacity 1
//Execution order
fun channelSend() = launch {
channel.send(1) //1
channel.send(1) //3
}
fun channelReceive() = launch {
val value1 = channel.receive() //2
val value2 = channel.receive() //4
}
Channels
● experimental
● hot observables in Rx world
● have buffer (default is 1)
● cold observables -
top issue
● cold observables ~
Sequences
val channel = Channel<Int>(1) // capacity 1
//Execution order
fun channelSend() = launch {
channel.send(1) //1
channel.send(1) //3
}
fun channelReceive() = launch {
val value1 = channel.receive() //2
val value2 = channel.receive() //4
}
Channels
● experimental
● hot observables in Rx world
● have buffer (default is 1)
● cold observables -
top issue
● cold observables ~
Sequences
val channel = Channel<Int>(1) // capacity 1
//Execution order
fun channelSend() = launch {
channel.send(1) //1
channel.send(1) //3
}
fun channelReceive() = launch {
val value1 = channel.receive() //2
val value2 = channel.receive() //4
}
Channels
● experimental
● hot observables in Rx world
● have buffer (default is 1)
● cold observables -
top issue
● cold observables ~
Sequences
val channel = Channel<Int>(1) // capacity 1
//Execution order
fun channelSend() = launch {
channel.send(1) //1
channel.send(1) //3
}
fun channelReceive() = launch {
val value1 = channel.receive() //2
val value2 = channel.receive() //4
}
Produce
val producer = produce{
send(1) //1
send(1) //3
}
fun receive() {
launch {
val value1 = producer.receive() //2
val value2 = producer.receive() //4
}
}
Actor
val subscriber = actor<Int> {
for(i in channel) {
//wait for elements in channel
}
}
fun send() {
launch {
subscriber.send(1)
subscriber.send(2)
}
}
Will it be the next step for RxJava
developer?
The next step for RxJava developer?
● Coroutines = low-level API for asynchronous calls
● Rx = observable pattern, "functional reactive programming"
● sequential vs streams, next tool in toolset
● Coroutines are faster and more memory efficient
● Perfectly replacement for Single, Completable, Maybe
● Easier to learn, lower entry threshold
● Can pass null values
● Channels can’t replace Observables
● Rx wins when dealing with real streams
● Coroutine wins with Kotlin/Native
● Rx API with Coroutines?
Should we switch to coroutines? IMHO
● You already have RxJava - stay with RxJava
● You are in love with RxJava - good
● You work with streams - only Rx
● You work with Java - Rx
● CRUD - Coroutines
● Simple app - Coroutines
● Don’t want Rx - only Coroutines
Where/What to learn more?
● https://github.com/Kotlin/kotlin-coroutines/ - core coroutine in language
● https://github.com/Kotlin/kotlinx.coroutines - base support library and other:
○ Dispatchers(“threads”) for Dispatchers.Main - Android, Spring, JavaFX
○ support for Reactive libraries - RxJava1, RxJava2, etc…
○ support for future-based libraries - JDK8, Guava, etc…
○ Kotlin/JS
○ Kotlin/Native
● KotlinConf talks about Coroutines by Roman Elizarov (2017, 2018)
Questions?
Coroutines, Kotlin, Ultimate Question of Life, the Universe,
and Everything?
@iiarchi
thecodeside.com

More Related Content

What's hot (20)

PDF
.NET Multithreading and File I/O
Jussi Pohjolainen
 
PDF
Python Async IO Horizon
Lukasz Dobrzanski
 
PDF
Actor Concurrency
Alex Miller
 
PPTX
Making Java more dynamic: runtime code generation for the JVM
Rafael Winterhalter
 
KEY
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Charles Nutter
 
PDF
Kotlin from-scratch 3 - coroutines
Franco Lombardo
 
PDF
Non stop random2b
phanhung20
 
PPT
About Those Python Async Concurrent Frameworks - Fantix @ OSTC 2014
Fantix King 王川
 
PDF
Concurrency Concepts in Java
Doug Hawkins
 
ODP
Java Concurrency
Carol McDonald
 
PDF
C++ game development with oxygine
corehard_by
 
TXT
Play image
Fardian Syah
 
PDF
Oxygine 2 d objects,events,debug and resources
corehard_by
 
PDF
Java 7 LavaJUG
julien.ponge
 
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
julien.ponge
 
PDF
Java Concurrency Gotchas
Alex Miller
 
PDF
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
soft-shake.ch
 
PPTX
Effective java - concurrency
feng lee
 
PDF
Java Concurrency Gotchas
Alex Miller
 
PDF
asyncio internals
Saúl Ibarra Corretgé
 
.NET Multithreading and File I/O
Jussi Pohjolainen
 
Python Async IO Horizon
Lukasz Dobrzanski
 
Actor Concurrency
Alex Miller
 
Making Java more dynamic: runtime code generation for the JVM
Rafael Winterhalter
 
Øredev 2011 - JVM JIT for Dummies (What the JVM Does With Your Bytecode When ...
Charles Nutter
 
Kotlin from-scratch 3 - coroutines
Franco Lombardo
 
Non stop random2b
phanhung20
 
About Those Python Async Concurrent Frameworks - Fantix @ OSTC 2014
Fantix King 王川
 
Concurrency Concepts in Java
Doug Hawkins
 
Java Concurrency
Carol McDonald
 
C++ game development with oxygine
corehard_by
 
Play image
Fardian Syah
 
Oxygine 2 d objects,events,debug and resources
corehard_by
 
Java 7 LavaJUG
julien.ponge
 
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
julien.ponge
 
Java Concurrency Gotchas
Alex Miller
 
soft-shake.ch - Java SE 7: The Fork/Join Framework and Project Coin
soft-shake.ch
 
Effective java - concurrency
feng lee
 
Java Concurrency Gotchas
Alex Miller
 
asyncio internals
Saúl Ibarra Corretgé
 

Similar to Kotlin coroutine - the next step for RxJava developer? (20)

PPTX
Coroutines talk ppt
Shahroz Khan
 
PDF
Improving app performance with Kotlin Coroutines
Hassan Abid
 
PDF
Quick Introduction to Kotlin Coroutine for Android Dev
Shuhei Shogen
 
PDF
Should it be routine to use coroutines?
Ion Stefan Brosteanu
 
PDF
Fabio Collini - Async code on Kotlin: RxJava or/and coroutines - Codemotion M...
Codemotion
 
PDF
Kotlin - Coroutine
Sean Tsai
 
PDF
Structured concurrency with Kotlin Coroutines
Vadims Savjolovs
 
PPTX
Kotlin Coroutines and Rx
Shaul Rosenzwieg
 
PDF
Coroutines in Kotlin. In-depth review
Dmytro Zaitsev
 
PDF
Coroutines in Kotlin. UA Mobile 2017.
UA Mobile
 
PDF
Coroutines and RxJava - An Asynchronicity Comparison
Manuel Vicente Vivo
 
PDF
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Lauren Yew
 
PDF
Asynchronous Programming in Kotlin with Coroutines
Tobias Schürg
 
PPTX
Coroutines in Kotlin
Alexey Soshin
 
PDF
Programação assíncrona utilizando Coroutines
Diego Gonçalves Santos
 
PDF
Introduction to kotlin coroutines
NAVER Engineering
 
PDF
KOTLIN COROUTINES - PART 1
Bartosz Kozajda
 
PDF
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Fabio Collini
 
PPTX
Kotlin coroutines and spring framework
Sunghyouk Bae
 
PDF
Coroutines for Kotlin Multiplatform in Practise
Christian Melchior
 
Coroutines talk ppt
Shahroz Khan
 
Improving app performance with Kotlin Coroutines
Hassan Abid
 
Quick Introduction to Kotlin Coroutine for Android Dev
Shuhei Shogen
 
Should it be routine to use coroutines?
Ion Stefan Brosteanu
 
Fabio Collini - Async code on Kotlin: RxJava or/and coroutines - Codemotion M...
Codemotion
 
Kotlin - Coroutine
Sean Tsai
 
Structured concurrency with Kotlin Coroutines
Vadims Savjolovs
 
Kotlin Coroutines and Rx
Shaul Rosenzwieg
 
Coroutines in Kotlin. In-depth review
Dmytro Zaitsev
 
Coroutines in Kotlin. UA Mobile 2017.
UA Mobile
 
Coroutines and RxJava - An Asynchronicity Comparison
Manuel Vicente Vivo
 
Threading Made Easy! A Busy Developer’s Guide to Kotlin Coroutines
Lauren Yew
 
Asynchronous Programming in Kotlin with Coroutines
Tobias Schürg
 
Coroutines in Kotlin
Alexey Soshin
 
Programação assíncrona utilizando Coroutines
Diego Gonçalves Santos
 
Introduction to kotlin coroutines
NAVER Engineering
 
KOTLIN COROUTINES - PART 1
Bartosz Kozajda
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Fabio Collini
 
Kotlin coroutines and spring framework
Sunghyouk Bae
 
Coroutines for Kotlin Multiplatform in Practise
Christian Melchior
 
Ad

Recently uploaded (20)

PDF
GetOnCRM Speeds Up Agentforce 3 Deployment for Enterprise AI Wins.pdf
GetOnCRM Solutions
 
PPTX
Tally software_Introduction_Presentation
AditiBansal54083
 
PPTX
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
PDF
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
PDF
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
PPTX
Java Native Memory Leaks: The Hidden Villain Behind JVM Performance Issues
Tier1 app
 
PDF
Executive Business Intelligence Dashboards
vandeslie24
 
PDF
Powering GIS with FME and VertiGIS - Peak of Data & AI 2025
Safe Software
 
PPTX
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
PPTX
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PPTX
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
PDF
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
PDF
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
PPTX
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
PDF
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
PPTX
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
PPTX
The Role of a PHP Development Company in Modern Web Development
SEO Company for School in Delhi NCR
 
PPTX
Human Resources Information System (HRIS)
Amity University, Patna
 
PDF
Unlock Efficiency with Insurance Policy Administration Systems
Insurance Tech Services
 
GetOnCRM Speeds Up Agentforce 3 Deployment for Enterprise AI Wins.pdf
GetOnCRM Solutions
 
Tally software_Introduction_Presentation
AditiBansal54083
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pptx
Varsha Nayak
 
Capcut Pro Crack For PC Latest Version {Fully Unlocked} 2025
hashhshs786
 
Automate Cybersecurity Tasks with Python
VICTOR MAESTRE RAMIREZ
 
Java Native Memory Leaks: The Hidden Villain Behind JVM Performance Issues
Tier1 app
 
Executive Business Intelligence Dashboards
vandeslie24
 
Powering GIS with FME and VertiGIS - Peak of Data & AI 2025
Safe Software
 
How Apagen Empowered an EPC Company with Engineering ERP Software
SatishKumar2651
 
Revolutionizing Code Modernization with AI
KrzysztofKkol1
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
3uTools Full Crack Free Version Download [Latest] 2025
muhammadgurbazkhan
 
Understanding the Need for Systemic Change in Open Source Through Intersectio...
Imma Valls Bernaus
 
Digger Solo: Semantic search and maps for your local files
seanpedersen96
 
Feb 2021 Cohesity first pitch presentation.pptx
enginsayin1
 
Beyond Binaries: Understanding Diversity and Allyship in a Global Workplace -...
Imma Valls Bernaus
 
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
The Role of a PHP Development Company in Modern Web Development
SEO Company for School in Delhi NCR
 
Human Resources Information System (HRIS)
Amity University, Patna
 
Unlock Efficiency with Insurance Policy Administration Systems
Insurance Tech Services
 
Ad

Kotlin coroutine - the next step for RxJava developer?

  • 1. Kotlin Coroutine - the next step for RxJava developer? Artur Latoszewski
  • 2. Agenda: 1. Pre-Kotlin world 2. What are coroutines and why we need it 3. Theoretical knowledge 4. Basic tutorial (some code) 5. Extra examples (more code) 6. Answer for the title question 7. Where to find more information
  • 3. What have we had in pre-Kotlin world? ● AsyncTasks ● Threads Painful points: ● Android Lifecycle ● Awful API ● Callbacks ● Easy to make a bug ● Hard to debug ● Concurrency is hard
  • 4. What have we had in pre-Kotlin world? - RxJava! http://reactivex.io/
  • 6. What are Coroutines for a developer? Coroutines allows us to write asynchronous code in sequential way. fun loadData() { var data = api.getData() showData(data) } sequential code (not coroutine)
  • 7. What problem does it solve?
  • 8. What problem does it solve? Callbacks! https://www.twilio.com/blog/2017/03/promises-in-swift-writing-cleaner-asynchronous-code-using-promisekit.html
  • 9. RxJava problems? Observable.just(1,2,3,4) .map { /*someMapping*/ } .filter { /*someFilter*/ } .subscribe( { /*onNext*/ }, { /*onError*/ } )
  • 10. RxJava problems? Observable.just(1,2,3,4) .map { /*someMapping*/ } .filter { /*someFilter*/ } .subscribe( { /*onNext*/ }, { /*onError*/ } ) Callbacks
  • 11. RxJava problems? Observable.just(1,2,3,4) .map { /*someMapping*/ } .filter { /*someFilter*/ } .subscribe( { /*onNext*/ }, { /*onError*/ } ) Callbacks Stream style
  • 13. Coroutines - deep dive ● conceptually very light-weight threads ● one thread = ∞ coroutines ● compiled to state machine with shared state (and callbacks) ● 100K Threads = 💔, 100K Coroutines = 💚 ● less context switch overhead ● less memory overhead ● works everywhere where Kotlin works ● stable since Kotlin 1.3
  • 14. Suspend function ● suspend and executed later ● without blocking thread ● without changing context ● almost free suspend fun doWorld() { println("World!") }
  • 15. Coroutine context = Job + Dispatcher Job (Rx ~ CompositeDisposable) ● a cancellable thing ● can’t be reused after cancel ● parent-child hierarchies ● SupervisorJob - child don’t cancel parent Dispatchers (Rx ~ Schedulers) ● Default - thread pool = CPU cores ● Main - run on main thread (main UI thread on Android) ● IO - designed for IO tasks, share with Default
  • 16. ● launch() - fire and forget ○ return Job object - allows to cancel coroutine ○ uncaught exceptions = crash ● async() - promise that it will return object ○ return Deferred<out T> : Job on which we call await() to wait for result ○ without await() call it will “swallow” exception ● runBlocking() - locks current thread until end of execution ● withContext() - run internal block on specified context Coroutine builder
  • 19. Coroutines - first val job = GlobalScope.launch(Dispatchers.Main){ println("We are in coroutine") }
  • 20. Coroutines - cancel val job = GlobalScope.launch(Dispatchers.Main){ println("We are in coroutine") } job.cancel() ------------------------------------------------------------------ RxJava disposable.dispose()
  • 21. Coroutines - cancel val job = launch (Dispatchers.Main){ while (true){ println("We are in coroutine") } } job.cancel()
  • 22. Coroutines - cancel val job = launch (Dispatchers.Main){ while (isActive){ println("We are in coroutine") } } job.cancel() ------------------------------------------------------------------ RxJava isDisposed()
  • 23. CoroutineScope public interface CoroutineScope { public val coroutineContext: CoroutineContext } ● every coroutine needs a scope (coroutine is extension method) ● scope is a lifecycle for a coroutine ● scopes creates “scope tree” ● you don’t want to use GlobalScope
  • 24. CoroutineScope - Activty class MyActivity : AppCompatActivity(), CoroutineScope { lateinit var parentJob: SupervisorJob override val coroutineContext: CoroutineContext = Dispatchers.Main + parentJob override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) parentJob = SupervisorJob() } override fun onDestroy() { super.onDestroy() parentJob.cancel() } }
  • 25. CoroutineScope - Activty class MyActivity : AppCompatActivity(), CoroutineScope { override val coroutineContext: CoroutineContext = Dispatchers.Main + parentJob fun buildCoroutineTree(){ launch { // MyActivity scope async { // launch scope } } launch { // MyActivity scope } } override fun onDestroy() { parentJob.cancel() // Cancel all coroutines in scope } }
  • 26. CoroutineScope - ViewModel class MyActivity : ViewModel(), CoroutineScope { val parentJob = SupervisorJob() override val coroutineContext: CoroutineContext = Dispatchers.Main + parentJob override fun onCleared() { super.onCleared() parentJob.cancel() } fun doSomeStuff() { launch{ // launch scope } } }
  • 27. CoroutineScope - ViewModel class MyActivity : ViewModel(), CoroutineScope { fun doSomeStuff() { viewModelScope.launch{ // launch scope } } } ● AndroidX Lifecycle v2.1.0 (alpha)
  • 28. Coroutines - change context (thread) launch (Dispatchers.Main){ println("Coroutine in main thread") withContext(Dispatchers.IO){ println("Coroutine in background thread") } println("Coroutine in main thread") } ------------------------------------------------------------------ RxJava .observeOn() .subscribeOn() .unsubscribeOn()
  • 29. Coroutines - sequentially fun loadDataSequentially() { launch(Dispatchers.Main) { val response1 = withContext(Dispatchers.IO) { loadData1() } // 1 val response2 = withContext(Dispatchers.IO) { loadData2() } // 2 val result = response1 + response2 // 3 } }
  • 30. Coroutines - sequentially fun loadDataSequentially() { launch(Dispatchers.Main) { val response1 = withContext(Dispatchers.IO) { loadData1() } // 1 val response2 = withContext(Dispatchers.IO) { loadData2() } // 2 val result = response1 + response2 // 3 } }
  • 31. Coroutines - asynchronous launch(Dispatchers.Main) { val response = async(Dispatchers.IO) { // Deferred<Response> println("We are in async coroutine") // doing stuff in background thread loadData() } // doing stuff main thread val value = response.await() // await for response }
  • 32. Coroutines - parallel fun loadDataParallel() { launch(Dispatchers.Main) { val response1 = async(Dispatchers.IO) { loadData1() } val response2 = async(Dispatchers.IO) { loadData2() } // doing stuff main thread val result = response1.await() + response1.await() //await for response } }
  • 33. Coroutines - parallel fun loadDataParallel() { launch(Dispatchers.Main) { val response1 = async(Dispatchers.IO) { loadData1() } val response2 = async(Dispatchers.IO) { loadData2() } // doing stuff main thread val result = response1.await() + response1.await() //await for response } }
  • 36. Operators? Everything from Kotlin Collections (map, filter, etc.) and more: fun loadDataWithTimeout() { launch(Dispatchers.Main) { val response = async(Dispatchers.IO) { loadData() } val result = withTimeoutOrNull(2, TimeUnit.SECONDS) { response.await() } }
  • 37. Retry suspend fun <T> retry(block: suspend (Int) -> T): T { for (i in 1..5) { // try 5 times try { return withTimeout(500) { // with timeout block(i) } } catch (e: TimeoutCancellationException) { /* retry */ } } return block(0) // last time just invoke without timeout }
  • 38. Retry suspend fun <T> retry(block: suspend (Int) -> T): T { for (i in 1..5) { // try 5 times try { return withTimeout(500) { // with timeout block(i) } } catch (e: TimeoutCancellationException) { /* retry */ } } return block(0) // last time just invoke without timeout }
  • 39. Retry suspend fun <T> retry(block: suspend (Int) -> T): T { for (i in 1..5) { // try 5 times try { return withTimeout(500) { // with timeout block(i) } } catch (e: TimeoutCancellationException) { /* retry */ } } return block(0) // last time just invoke without timeout }
  • 40. Retry suspend fun <T> retry(block: suspend (Int) -> T): T { for (i in 1..5) { // try 5 times try { return withTimeout(500) { // with timeout block(i) } } catch (e: TimeoutCancellationException) { /* retry */ } } return block(0) // last time just invoke without timeout }
  • 41. Retry suspend fun <T> retry(block: suspend (Int) -> T): T { for (i in 1..5) { // try 5 times try { return withTimeout(500) { // with timeout block(i) } } catch (e: TimeoutCancellationException) { /* retry */ } } return block(0) // last time just invoke without timeout }
  • 42. Retry suspend fun <T> retry(block: suspend (Int) -> T): T { for (i in 1..5) { // try 5 times try { return withTimeout(500) { // with timeout block(i) } } catch (e: TimeoutCancellationException) { /* retry */ } } return block(0) // last time just invoke without timeout }
  • 43. Retrofit interface RemoteDataSource{ @GET("api/news") fun getNews() : Single<NewsResponse> } ------------------------------------------------------------------ interface RemoteDataSource { @GET("api/news") fun getNews(): Deferred<NewsResponse> } ------------------------------------------------------------------ interface RemoteDataSource { @GET("api/news") suspend fun getNews(): NewsResponse } RxJava Adapter by JakeWharton Retrofit 2.5.1
  • 44. Channels ● experimental ● hot observables in Rx world ● have buffer (default is 1) ● cold observables - top issue ● cold observables ~ Sequences val channel = Channel<Int>(1) // capacity 1 //Execution order fun channelSend() = launch { channel.send(1) //1 channel.send(1) //3 } fun channelReceive() = launch { val value1 = channel.receive() //2 val value2 = channel.receive() //4 }
  • 45. Channels ● experimental ● hot observables in Rx world ● have buffer (default is 1) ● cold observables - top issue ● cold observables ~ Sequences val channel = Channel<Int>(1) // capacity 1 //Execution order fun channelSend() = launch { channel.send(1) //1 channel.send(1) //3 } fun channelReceive() = launch { val value1 = channel.receive() //2 val value2 = channel.receive() //4 }
  • 46. Channels ● experimental ● hot observables in Rx world ● have buffer (default is 1) ● cold observables - top issue ● cold observables ~ Sequences val channel = Channel<Int>(1) // capacity 1 //Execution order fun channelSend() = launch { channel.send(1) //1 channel.send(1) //3 } fun channelReceive() = launch { val value1 = channel.receive() //2 val value2 = channel.receive() //4 }
  • 47. Channels ● experimental ● hot observables in Rx world ● have buffer (default is 1) ● cold observables - top issue ● cold observables ~ Sequences val channel = Channel<Int>(1) // capacity 1 //Execution order fun channelSend() = launch { channel.send(1) //1 channel.send(1) //3 } fun channelReceive() = launch { val value1 = channel.receive() //2 val value2 = channel.receive() //4 }
  • 48. Channels ● experimental ● hot observables in Rx world ● have buffer (default is 1) ● cold observables - top issue ● cold observables ~ Sequences val channel = Channel<Int>(1) // capacity 1 //Execution order fun channelSend() = launch { channel.send(1) //1 channel.send(1) //3 } fun channelReceive() = launch { val value1 = channel.receive() //2 val value2 = channel.receive() //4 }
  • 49. Channels ● experimental ● hot observables in Rx world ● have buffer (default is 1) ● cold observables - top issue ● cold observables ~ Sequences val channel = Channel<Int>(1) // capacity 1 //Execution order fun channelSend() = launch { channel.send(1) //1 channel.send(1) //3 } fun channelReceive() = launch { val value1 = channel.receive() //2 val value2 = channel.receive() //4 }
  • 50. Produce val producer = produce{ send(1) //1 send(1) //3 } fun receive() { launch { val value1 = producer.receive() //2 val value2 = producer.receive() //4 } }
  • 51. Actor val subscriber = actor<Int> { for(i in channel) { //wait for elements in channel } } fun send() { launch { subscriber.send(1) subscriber.send(2) } }
  • 52. Will it be the next step for RxJava developer?
  • 53. The next step for RxJava developer? ● Coroutines = low-level API for asynchronous calls ● Rx = observable pattern, "functional reactive programming" ● sequential vs streams, next tool in toolset ● Coroutines are faster and more memory efficient ● Perfectly replacement for Single, Completable, Maybe ● Easier to learn, lower entry threshold ● Can pass null values ● Channels can’t replace Observables ● Rx wins when dealing with real streams ● Coroutine wins with Kotlin/Native ● Rx API with Coroutines?
  • 54. Should we switch to coroutines? IMHO ● You already have RxJava - stay with RxJava ● You are in love with RxJava - good ● You work with streams - only Rx ● You work with Java - Rx ● CRUD - Coroutines ● Simple app - Coroutines ● Don’t want Rx - only Coroutines
  • 55. Where/What to learn more? ● https://github.com/Kotlin/kotlin-coroutines/ - core coroutine in language ● https://github.com/Kotlin/kotlinx.coroutines - base support library and other: ○ Dispatchers(“threads”) for Dispatchers.Main - Android, Spring, JavaFX ○ support for Reactive libraries - RxJava1, RxJava2, etc… ○ support for future-based libraries - JDK8, Guava, etc… ○ Kotlin/JS ○ Kotlin/Native ● KotlinConf talks about Coroutines by Roman Elizarov (2017, 2018)
  • 56. Questions? Coroutines, Kotlin, Ultimate Question of Life, the Universe, and Everything? @iiarchi thecodeside.com