SlideShare a Scribd company logo
1 of 40
Download to read offline
Kotlin Coroutines:
Multi-threading made easy
Arthur Nagy
Halcyon Mobile
Agenda
1. What are coroutines
2. Coroutines in Android
3. Why use coroutines
What are coroutines
“coroutines are computations that can be suspended
without blocking a thread.”
● Not a new concept, introduced in the `60s
● Adopted by multiple programming languages
● Coroutines in Kotlin:
○ minimal low-level APIs in its standard library
○ kotlinx.coroutines libraries
What are coroutines
● Terminology :
○ Coroutine
○ Suspending function
○ Coroutine builder
○ Continuation
○ Coroutine context
Coroutine
● An instance of suspendable computation
● Similar to a thread (light-weight thread)
● Also similar to a future or promise
Suspending functions
● Functions which suspend a coroutine execution
● suspend keyword
● Suspending functions can be used:
○ Inside other functions marked with the suspend keyword
○ Inside a coroutine
● suspendCoroutine
○ Bridge between coroutine suspension and callback world
Suspending functions
/**
* Obtains the current continuation instance
* inside suspend functions and suspends
* currently running coroutine.
*/
suspend inline fun <T> suspendCoroutine(
crossinline block: (Continuation<T>) -> Unit): T =
Suspending functions
public interface Continuation<in T> {
public val context: CoroutineContext
public fun resume(value: T)
public fun resumeWithException(exception: Throwable)
}
Suspending functions
suspend fun firstFun(): ResultType = suspendCoroutine { continuation ->
// do some heavy work
// resume the coroutine continuation with a result:
continuation.resume(result)
// or if there was an error:
continuation.resumeWithException(exception)
}
Coroutine builders
● Functions which start a coroutine
● Bridge between non-coroutine & coroutine world
● Most common coroutine builders:
○ launch
○ async
○ withContext
Coroutine builders
launch {
// everything inside happens on
// a background thread pool
}
// continue app operations
Coroutine builders
fun launch(
context: CoroutineContext = Dispatchers.Default,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
Coroutine builders
val result: Deferred<T> = async {
// do stuff on the background thread
// which returns a value T when done
}
result.await()
Coroutine builders
val result: T = withContext(BACKGROUND) {
// do stuff on the background thread
// which returns a value T when done
}
Coroutines in Android
Coroutines in Android
kotlin {
experimental {
coroutines 'enable'
}
}
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.25.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0'
}
class BlurActivity : AppCompatActivity() {
...
override fun onActivityResult(requestC: Int, resultC: Int, data: Intent?) {
val imageUri = data?.data
launch(UI) {
val resultImage = withContext(BACKGROUND) {
blurImage(imageUri)
}
viewBinding.image.setImageURI(resultImage)
viewModel.uploadImage(resultImage)
}
}
...
}
suspend fun blurImage(imageUri: Uri): Uri = suspendCoroutine { continuation ->
try {
val imageBitmap = getBitmapFromImageUri(imageUri)
val blurredImage = applyBlurOnBitmap(imageBitmap)
val blurredImageFile = saveBitmapToTemporaryFile(blurredImage)
continuation.resume(blurredImageFile)
} catch (e: Exception) {
continuation.resumeWithException(e)
}
}
class BlurActivity : AppCompatActivity() {
...
override fun onActivityResult(requestC: Int, resultC: Int, data: Intent?) {
val imageUri = data?.data
launch(UI) {
val resultImage = withContext(BACKGROUND) {
blurImage(imageUri)
}
viewBinding.image.setImageURI(resultImage)
viewModel.uploadImage(resultImage)
}
}
...
}
class BlurViewModel(
private val restApiService: RestApiService
) : ViewModel() {
...
fun uploadImage(imageUri: Uri) {
// update UI state, i.e: show progress, etc
launch(BACKGROUND) {
val imageFile = File(imageUri.path)
val imageFilePart = createImagePart(imageFile)
val response = restApiService.uploadBlurredImage(imageFilePart).await()
// use our response to update UI state, etc.
}
}
...
}
restApiService.uploadBlurredImage(imageFilePart).enqueue(Callback<> {
override fun onResponse(call, response) {
if (response.isSuccessful){
val blurResponse = response.body()!!
// use our response to update UI state, etc.
}
}
override fun onFailure(call, throwable) {
}
})
launch(BACKGROUND) {
val response = restApiService.uploadBlurredImage(imageFilePart).await()
}
interface RestApiService {
@Multipart
@POST("/blurred_image")
fun uploadBlurredImage(@Part file: Part): Call<BlurResponse>
}
suspend fun <T> Call<T>.await(): T = suspendCoroutine { continuation ->
enqueue(object: Callback<T> {
override fun onResponse(call: Call<T>, response: Response<T>) {
if (response.isSuccessful) {
continuation.resume(response.body()!!)
} else {
continuation.resumeWithException(RequestException(response.message()))
}
}
override fun onFailure(call: Call<T>, t: Throwable) {
continuation.resumeWithException(t)
}
})
}
What about Android
lifecycle handling &
cancelation?
class BlurActivity : AppCompatActivity() {
...
launch(UI) {
val resultImage = withContext(BACKGROUND) {
blurImage(imageUri)
}
}
...
}
class BlurActivity : AppCompatActivity() {
...
val job = launch(UI) {
val resultImage = withContext(BACKGROUND) {
blurImage(imageUri)
}
}
...
override fun onStop() {
super.onStop()
job.cancel()
}
}
class CoroutineLifecycleObserver : LifecycleObserver {
var parentJob: Job = Job()
@OnLifecycleEvent(Lifecycle.Event.ON_START) fun start() {
if (parentJob.isCompleted) {
parentJob = Job()
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun cancel() {
if (parentJob.isActive) {
parentJob.cancel()
}
}
}
gist.github.com/chrisbanes/152d325211401843326068c24e0d11b1
class BlurActivity : AppCompatActivity() {
private val coroutineObserver = CoroutineLifecycleObserver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
lifecycle.addObserver(coroutineObserver)
}
launch(context = UI, parent = coroutineObserver.job) {
val resultImage = withContext(BACKGROUND) {
blurImage(imageUri)
}
}
}
open class CoroutineViewModel : ViewModel() {
private val parentJob = Job()
override fun onCleared() {
super.onCleared()
parentJob.cancel()
}
protected fun launchWithParent(
context: CoroutineContext = BACKGROUND,
block: suspend CoroutineScope.() -> Unit
) = launch(context = context, parent = parentJob, block = block)
}
class BlurViewModel(
private val restApiService: RestApiService
) : CoroutineViewModel() {
fun uploadImage(imageUri: Uri) {
launchWithParent(BACKGROUND) {
...
}
}
}
Why use coroutines
● Asynchronous code sequentially
● No more callback-hell
asyncOperation(object: Callback {
fun onSuccess(result) {
anotherOne(result, object: Callback {
fun onSuccess(secondResult){
lastOne(secondResult, object: Callback {
fun onSuccess(thirdResult){
useResult(thirdResult)
}
fun onError(exception){
handleError(exception)
}
})
}
fun onError(exception){
handleError(exception)
}
})
}
fun onError(exception) {
handleError(exception)
}
})
Why use coroutines
● Asynchronous code sequentially
● No more callback-hell
● “It’s experimental, we can’t use it!”
● “We already have so many options, why use this one?!”
Why use coroutines
val blurAsyncTask = object : AsyncTask<Uri, Int, Uri>() {
override fun doInBackground(vararg params: Uri?): Uri {
return blurImage(params)
}
override fun onPostExecute(result: Uri?) {
viewBinding.image.setImageURI(result)
viewModel.uploadImage(result)
}
}
blurAsyncTask.execute(imageUri)
Why use coroutines
private val executors = Executors.newCachedThreadPool()
fun uploadImage(imageUri: Uri) {
executors.execute {
val imageFile = File(imageUri.path)
val imageFilePart = createImagePart(imageFile)
restApiService.uploadBlurredImage(imageFilePart).enqueue(Callback<> {
override fun onResponse(response: Response<>) {
// use the response to update state, etc.
}
override fun onFailure(t: Throwable) {
}
})
}
}
Why use coroutines
disposables.add(Single
.fromCallable { blurImage(imageUri) }
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ resultImage ->
viewBinding.image.setImageURI(resultImage)
viewModel.uploadImage(resultImage)
},{ error ->
})
)
Why use coroutines
fun uploadImage(imageUri: Uri) {
disposables.add(Single.fromCallable {
val imageFile = File(imageUri.path)
createImagePart(imageFile)
}.flatMap(restApiService::uploadBlurredImage)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ blurResponse ->
//update UI state, etc.
}, { error ->
})
)
}
● There’s a lot more:
○ Exception handling, channels, actors, etc.
● Resources:
○ kotlinlang.org/docs/reference/coroutines.html
○ github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-infor
mal.md
○ github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
○ gist.github.com/chrisbanes/152d325211401843326068c24e0d11b1
○ github.com/gildor/kotlin-coroutines-retrofit
Thank you!
● twitter.com/android_halcyon
● medium.com/halcyon-mobile
● halcyonmobile.com
● arthurnagy.me

More Related Content

What's hot

Deep dive into Android async operations
Deep dive into Android async operationsDeep dive into Android async operations
Deep dive into Android async operationsMateusz Grzechociński
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threadsYnon Perek
 
Technical Deep Dive into the New Prefab System
Technical Deep Dive into the New Prefab SystemTechnical Deep Dive into the New Prefab System
Technical Deep Dive into the New Prefab SystemUnity Technologies
 
Best Practices in Qt Quick/QML - Part 1 of 4
Best Practices in Qt Quick/QML - Part 1 of 4Best Practices in Qt Quick/QML - Part 1 of 4
Best Practices in Qt Quick/QML - Part 1 of 4ICS
 
Functional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event SystemsFunctional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event SystemsLeonardo Borges
 
QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? ICS
 
Intro to Clojure's core.async
Intro to Clojure's core.asyncIntro to Clojure's core.async
Intro to Clojure's core.asyncLeonardo Borges
 
Intro to QML / Declarative UI
Intro to QML / Declarative UIIntro to QML / Declarative UI
Intro to QML / Declarative UIOpenBossa
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScriptMichael Girouard
 
Qt for beginners part 1 overview and key concepts
Qt for beginners part 1   overview and key conceptsQt for beginners part 1   overview and key concepts
Qt for beginners part 1 overview and key conceptsICS
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationIvan Dolgushin
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simplerAlexander Mostovenko
 
Qt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickQt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickICS
 
Introducing the New Prefab Workflow - Unite LA
Introducing the New Prefab Workflow - Unite LAIntroducing the New Prefab Workflow - Unite LA
Introducing the New Prefab Workflow - Unite LAUnity Technologies
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to missAndres Almiray
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engineDuoyi Wu
 

What's hot (20)

Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
 
Deep dive into Android async operations
Deep dive into Android async operationsDeep dive into Android async operations
Deep dive into Android async operations
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threads
 
Technical Deep Dive into the New Prefab System
Technical Deep Dive into the New Prefab SystemTechnical Deep Dive into the New Prefab System
Technical Deep Dive into the New Prefab System
 
Best Practices in Qt Quick/QML - Part 1 of 4
Best Practices in Qt Quick/QML - Part 1 of 4Best Practices in Qt Quick/QML - Part 1 of 4
Best Practices in Qt Quick/QML - Part 1 of 4
 
Twins: OOP and FP
Twins: OOP and FPTwins: OOP and FP
Twins: OOP and FP
 
Functional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event SystemsFunctional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event Systems
 
QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong?
 
Intro to Clojure's core.async
Intro to Clojure's core.asyncIntro to Clojure's core.async
Intro to Clojure's core.async
 
Intro to QML / Declarative UI
Intro to QML / Declarative UIIntro to QML / Declarative UI
Intro to QML / Declarative UI
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
 
Qt for beginners part 1 overview and key concepts
Qt for beginners part 1   overview and key conceptsQt for beginners part 1   overview and key concepts
Qt for beginners part 1 overview and key concepts
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simpler
 
Qt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt QuickQt for Beginners Part 3 - QML and Qt Quick
Qt for Beginners Part 3 - QML and Qt Quick
 
Introducing the New Prefab Workflow - Unite LA
Introducing the New Prefab Workflow - Unite LAIntroducing the New Prefab Workflow - Unite LA
Introducing the New Prefab Workflow - Unite LA
 
Java libraries you can't afford to miss
Java libraries you can't afford to missJava libraries you can't afford to miss
Java libraries you can't afford to miss
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
 
Exploring Kotlin
Exploring KotlinExploring Kotlin
Exploring Kotlin
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 

Similar to droidcon Transylvania - Kotlin Coroutines

Aplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e JetpackAplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e JetpackNelson Glauber Leal
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackNelson Glauber Leal
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackNelson Glauber Leal
 
Building Mobile Apps with Android
Building Mobile Apps with AndroidBuilding Mobile Apps with Android
Building Mobile Apps with AndroidKurt Renzo Acosta
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackNelson Glauber Leal
 
Kotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutinesKotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutinesFranco Lombardo
 
Practical tips for building apps with kotlin
Practical tips for building apps with kotlinPractical tips for building apps with kotlin
Practical tips for building apps with kotlinAdit Lal
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseChristian Melchior
 
Performance #6 threading
Performance #6  threadingPerformance #6  threading
Performance #6 threadingVitali Pekelis
 
Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android developmentAdit Lal
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutinesNAVER Engineering
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - CoroutineSean Tsai
 
KOTLIN COROUTINES - PART 1
KOTLIN COROUTINES - PART 1KOTLIN COROUTINES - PART 1
KOTLIN COROUTINES - PART 1Bartosz Kozajda
 
What’s new in Kotlin?
What’s new in Kotlin?What’s new in Kotlin?
What’s new in Kotlin?Squareboat
 
Having Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo SurabayaHaving Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo SurabayaDILo Surabaya
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleThierry Wasylczenko
 
Android Jetpack + Coroutines: To infinity and beyond
Android Jetpack + Coroutines: To infinity and beyondAndroid Jetpack + Coroutines: To infinity and beyond
Android Jetpack + Coroutines: To infinity and beyondRamon Ribeiro Rabello
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyMobileAcademy
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Danny Preussler
 

Similar to droidcon Transylvania - Kotlin Coroutines (20)

Aplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e JetpackAplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e Jetpack
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
 
Building Mobile Apps with Android
Building Mobile Apps with AndroidBuilding Mobile Apps with Android
Building Mobile Apps with Android
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
 
Kotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutinesKotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutines
 
Practical tips for building apps with kotlin
Practical tips for building apps with kotlinPractical tips for building apps with kotlin
Practical tips for building apps with kotlin
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in Practise
 
Performance #6 threading
Performance #6  threadingPerformance #6  threading
Performance #6 threading
 
Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android development
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - Coroutine
 
KOTLIN COROUTINES - PART 1
KOTLIN COROUTINES - PART 1KOTLIN COROUTINES - PART 1
KOTLIN COROUTINES - PART 1
 
What’s new in Kotlin?
What’s new in Kotlin?What’s new in Kotlin?
What’s new in Kotlin?
 
Having Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo SurabayaHaving Fun with Kotlin Android - DILo Surabaya
Having Fun with Kotlin Android - DILo Surabaya
 
Construire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradleConstruire une application JavaFX 8 avec gradle
Construire une application JavaFX 8 avec gradle
 
Android Jetpack + Coroutines: To infinity and beyond
Android Jetpack + Coroutines: To infinity and beyondAndroid Jetpack + Coroutines: To infinity and beyond
Android Jetpack + Coroutines: To infinity and beyond
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016
 

Recently uploaded

MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样umasea
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureDinusha Kumarasiri
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...Technogeeks
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 

Recently uploaded (20)

MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
办理学位证(UQ文凭证书)昆士兰大学毕业证成绩单原版一模一样
 
Implementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with AzureImplementing Zero Trust strategy with Azure
Implementing Zero Trust strategy with Azure
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...What is Advanced Excel and what are some best practices for designing and cre...
What is Advanced Excel and what are some best practices for designing and cre...
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 

droidcon Transylvania - Kotlin Coroutines

  • 1. Kotlin Coroutines: Multi-threading made easy Arthur Nagy Halcyon Mobile
  • 2. Agenda 1. What are coroutines 2. Coroutines in Android 3. Why use coroutines
  • 3. What are coroutines “coroutines are computations that can be suspended without blocking a thread.” ● Not a new concept, introduced in the `60s ● Adopted by multiple programming languages ● Coroutines in Kotlin: ○ minimal low-level APIs in its standard library ○ kotlinx.coroutines libraries
  • 4. What are coroutines ● Terminology : ○ Coroutine ○ Suspending function ○ Coroutine builder ○ Continuation ○ Coroutine context
  • 5. Coroutine ● An instance of suspendable computation ● Similar to a thread (light-weight thread) ● Also similar to a future or promise
  • 6. Suspending functions ● Functions which suspend a coroutine execution ● suspend keyword ● Suspending functions can be used: ○ Inside other functions marked with the suspend keyword ○ Inside a coroutine ● suspendCoroutine ○ Bridge between coroutine suspension and callback world
  • 7. Suspending functions /** * Obtains the current continuation instance * inside suspend functions and suspends * currently running coroutine. */ suspend inline fun <T> suspendCoroutine( crossinline block: (Continuation<T>) -> Unit): T =
  • 8. Suspending functions public interface Continuation<in T> { public val context: CoroutineContext public fun resume(value: T) public fun resumeWithException(exception: Throwable) }
  • 9. Suspending functions suspend fun firstFun(): ResultType = suspendCoroutine { continuation -> // do some heavy work // resume the coroutine continuation with a result: continuation.resume(result) // or if there was an error: continuation.resumeWithException(exception) }
  • 10. Coroutine builders ● Functions which start a coroutine ● Bridge between non-coroutine & coroutine world ● Most common coroutine builders: ○ launch ○ async ○ withContext
  • 11. Coroutine builders launch { // everything inside happens on // a background thread pool } // continue app operations
  • 12. Coroutine builders fun launch( context: CoroutineContext = Dispatchers.Default, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job
  • 13. Coroutine builders val result: Deferred<T> = async { // do stuff on the background thread // which returns a value T when done } result.await()
  • 14. Coroutine builders val result: T = withContext(BACKGROUND) { // do stuff on the background thread // which returns a value T when done }
  • 16. Coroutines in Android kotlin { experimental { coroutines 'enable' } } dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.25.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:0.25.0' }
  • 17. class BlurActivity : AppCompatActivity() { ... override fun onActivityResult(requestC: Int, resultC: Int, data: Intent?) { val imageUri = data?.data launch(UI) { val resultImage = withContext(BACKGROUND) { blurImage(imageUri) } viewBinding.image.setImageURI(resultImage) viewModel.uploadImage(resultImage) } } ... }
  • 18. suspend fun blurImage(imageUri: Uri): Uri = suspendCoroutine { continuation -> try { val imageBitmap = getBitmapFromImageUri(imageUri) val blurredImage = applyBlurOnBitmap(imageBitmap) val blurredImageFile = saveBitmapToTemporaryFile(blurredImage) continuation.resume(blurredImageFile) } catch (e: Exception) { continuation.resumeWithException(e) } }
  • 19. class BlurActivity : AppCompatActivity() { ... override fun onActivityResult(requestC: Int, resultC: Int, data: Intent?) { val imageUri = data?.data launch(UI) { val resultImage = withContext(BACKGROUND) { blurImage(imageUri) } viewBinding.image.setImageURI(resultImage) viewModel.uploadImage(resultImage) } } ... }
  • 20. class BlurViewModel( private val restApiService: RestApiService ) : ViewModel() { ... fun uploadImage(imageUri: Uri) { // update UI state, i.e: show progress, etc launch(BACKGROUND) { val imageFile = File(imageUri.path) val imageFilePart = createImagePart(imageFile) val response = restApiService.uploadBlurredImage(imageFilePart).await() // use our response to update UI state, etc. } } ... }
  • 21. restApiService.uploadBlurredImage(imageFilePart).enqueue(Callback<> { override fun onResponse(call, response) { if (response.isSuccessful){ val blurResponse = response.body()!! // use our response to update UI state, etc. } } override fun onFailure(call, throwable) { } })
  • 22. launch(BACKGROUND) { val response = restApiService.uploadBlurredImage(imageFilePart).await() }
  • 23. interface RestApiService { @Multipart @POST("/blurred_image") fun uploadBlurredImage(@Part file: Part): Call<BlurResponse> }
  • 24. suspend fun <T> Call<T>.await(): T = suspendCoroutine { continuation -> enqueue(object: Callback<T> { override fun onResponse(call: Call<T>, response: Response<T>) { if (response.isSuccessful) { continuation.resume(response.body()!!) } else { continuation.resumeWithException(RequestException(response.message())) } } override fun onFailure(call: Call<T>, t: Throwable) { continuation.resumeWithException(t) } }) }
  • 25. What about Android lifecycle handling & cancelation?
  • 26. class BlurActivity : AppCompatActivity() { ... launch(UI) { val resultImage = withContext(BACKGROUND) { blurImage(imageUri) } } ... }
  • 27. class BlurActivity : AppCompatActivity() { ... val job = launch(UI) { val resultImage = withContext(BACKGROUND) { blurImage(imageUri) } } ... override fun onStop() { super.onStop() job.cancel() } }
  • 28. class CoroutineLifecycleObserver : LifecycleObserver { var parentJob: Job = Job() @OnLifecycleEvent(Lifecycle.Event.ON_START) fun start() { if (parentJob.isCompleted) { parentJob = Job() } } @OnLifecycleEvent(Lifecycle.Event.ON_STOP) fun cancel() { if (parentJob.isActive) { parentJob.cancel() } } } gist.github.com/chrisbanes/152d325211401843326068c24e0d11b1
  • 29. class BlurActivity : AppCompatActivity() { private val coroutineObserver = CoroutineLifecycleObserver() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ... lifecycle.addObserver(coroutineObserver) } launch(context = UI, parent = coroutineObserver.job) { val resultImage = withContext(BACKGROUND) { blurImage(imageUri) } } }
  • 30. open class CoroutineViewModel : ViewModel() { private val parentJob = Job() override fun onCleared() { super.onCleared() parentJob.cancel() } protected fun launchWithParent( context: CoroutineContext = BACKGROUND, block: suspend CoroutineScope.() -> Unit ) = launch(context = context, parent = parentJob, block = block) }
  • 31. class BlurViewModel( private val restApiService: RestApiService ) : CoroutineViewModel() { fun uploadImage(imageUri: Uri) { launchWithParent(BACKGROUND) { ... } } }
  • 32. Why use coroutines ● Asynchronous code sequentially ● No more callback-hell
  • 33. asyncOperation(object: Callback { fun onSuccess(result) { anotherOne(result, object: Callback { fun onSuccess(secondResult){ lastOne(secondResult, object: Callback { fun onSuccess(thirdResult){ useResult(thirdResult) } fun onError(exception){ handleError(exception) } }) } fun onError(exception){ handleError(exception) } }) } fun onError(exception) { handleError(exception) } })
  • 34. Why use coroutines ● Asynchronous code sequentially ● No more callback-hell ● “It’s experimental, we can’t use it!” ● “We already have so many options, why use this one?!”
  • 35. Why use coroutines val blurAsyncTask = object : AsyncTask<Uri, Int, Uri>() { override fun doInBackground(vararg params: Uri?): Uri { return blurImage(params) } override fun onPostExecute(result: Uri?) { viewBinding.image.setImageURI(result) viewModel.uploadImage(result) } } blurAsyncTask.execute(imageUri)
  • 36. Why use coroutines private val executors = Executors.newCachedThreadPool() fun uploadImage(imageUri: Uri) { executors.execute { val imageFile = File(imageUri.path) val imageFilePart = createImagePart(imageFile) restApiService.uploadBlurredImage(imageFilePart).enqueue(Callback<> { override fun onResponse(response: Response<>) { // use the response to update state, etc. } override fun onFailure(t: Throwable) { } }) } }
  • 37. Why use coroutines disposables.add(Single .fromCallable { blurImage(imageUri) } .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ resultImage -> viewBinding.image.setImageURI(resultImage) viewModel.uploadImage(resultImage) },{ error -> }) )
  • 38. Why use coroutines fun uploadImage(imageUri: Uri) { disposables.add(Single.fromCallable { val imageFile = File(imageUri.path) createImagePart(imageFile) }.flatMap(restApiService::uploadBlurredImage) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ blurResponse -> //update UI state, etc. }, { error -> }) ) }
  • 39. ● There’s a lot more: ○ Exception handling, channels, actors, etc. ● Resources: ○ kotlinlang.org/docs/reference/coroutines.html ○ github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-infor mal.md ○ github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md ○ gist.github.com/chrisbanes/152d325211401843326068c24e0d11b1 ○ github.com/gildor/kotlin-coroutines-retrofit
  • 40. Thank you! ● twitter.com/android_halcyon ● medium.com/halcyon-mobile ● halcyonmobile.com ● arthurnagy.me