SlideShare ist ein Scribd-Unternehmen logo
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

Weitere ähnliche Inhalte

Was ist angesagt?

Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
Matthew Clarke
 
Deep dive into Android async operations
Deep dive into Android async operationsDeep dive into Android async operations
Deep dive into Android async operations
Mateusz Grzechociński
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threads
Ynon 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 System
Unity 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 4
ICS
 
Twins: OOP and FP
Twins: OOP and FPTwins: OOP and FP
Twins: OOP and FP
RichardWarburton
 
Functional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event SystemsFunctional Reactive Programming / Compositional Event Systems
Functional Reactive Programming / Compositional Event Systems
Leonardo 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.async
Leonardo Borges
 
Intro to QML / Declarative UI
Intro to QML / Declarative UIIntro to QML / Declarative UI
Intro to QML / Declarative UI
OpenBossa
 
Object Oriented JavaScript
Object Oriented JavaScriptObject Oriented JavaScript
Object Oriented JavaScript
Michael 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 concepts
ICS
 
Using Reflections and Automatic Code Generation
Using Reflections and Automatic Code GenerationUsing Reflections and Automatic Code Generation
Using Reflections and Automatic Code Generation
Ivan Dolgushin
 
rx.js make async programming simpler
rx.js make async programming simplerrx.js make async programming simpler
rx.js make async programming simpler
Alexander 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 Quick
ICS
 
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
Unity 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 miss
Andres Almiray
 
Virtual machine and javascript engine
Virtual machine and javascript engineVirtual machine and javascript engine
Virtual machine and javascript engine
Duoyi Wu
 
Exploring Kotlin
Exploring KotlinExploring Kotlin
Exploring Kotlin
Atiq Ur Rehman
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
Guido Pio Mariotti
 

Was ist angesagt? (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
 

Ähnlich wie 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 Jetpack
Nelson 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 & Jetpack
Nelson 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 & Jetpack
Nelson Glauber Leal
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
Minseo Chayabanjonglerd
 
Building Mobile Apps with Android
Building Mobile Apps with AndroidBuilding Mobile Apps with Android
Building Mobile Apps with Android
Kurt 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 & Jetpack
Nelson Glauber Leal
 
Kotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutinesKotlin from-scratch 3 - coroutines
Kotlin from-scratch 3 - coroutines
Franco 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 kotlin
Adit Lal
 
Coroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in PractiseCoroutines for Kotlin Multiplatform in Practise
Coroutines for Kotlin Multiplatform in Practise
Christian Melchior
 
Performance #6 threading
Performance #6  threadingPerformance #6  threading
Performance #6 threading
Vitali 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 development
Adit Lal
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
NAVER Engineering
 
Kotlin - Coroutine
Kotlin - CoroutineKotlin - Coroutine
Kotlin - Coroutine
Sean Tsai
 
KOTLIN COROUTINES - PART 1
KOTLIN COROUTINES - PART 1KOTLIN COROUTINES - PART 1
KOTLIN COROUTINES - PART 1
Bartosz 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 Surabaya
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
Thierry 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 beyond
Ramon Ribeiro Rabello
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
MobileAcademy
 
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
Danny Preussler
 

Ähnlich wie 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
 

Kürzlich hochgeladen

Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
Philip Schwarz
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
brainerhub1
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
sjcobrien
 
Liberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptxLiberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptx
Massimo Artizzu
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
Peter Muessig
 
Oracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptxOracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptx
Remote DBA Services
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
rodomar2
 
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
mz5nrf0n
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
Octavian Nadolu
 
一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
dakas1
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
Remote DBA Services
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
Quickdice ERP
 
fiscal year variant fiscal year variant.
fiscal year variant fiscal year variant.fiscal year variant fiscal year variant.
fiscal year variant fiscal year variant.
AnkitaPandya11
 
What next after learning python programming basics
What next after learning python programming basicsWhat next after learning python programming basics
What next after learning python programming basics
Rakesh Kumar R
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
TaghreedAltamimi
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
ICS
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
safelyiotech
 
SQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure MalaysiaSQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure Malaysia
GohKiangHock
 

Kürzlich hochgeladen (20)

Hand Rolled Applicative User Validation Code Kata
Hand Rolled Applicative User ValidationCode KataHand Rolled Applicative User ValidationCode Kata
Hand Rolled Applicative User Validation Code Kata
 
Unveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdfUnveiling the Advantages of Agile Software Development.pdf
Unveiling the Advantages of Agile Software Development.pdf
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
 
Liberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptxLiberarsi dai framework con i Web Component.pptx
Liberarsi dai framework con i Web Component.pptx
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
 
Oracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptxOracle 23c New Features For DBAs and Developers.pptx
Oracle 23c New Features For DBAs and Developers.pptx
 
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CDKuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
KuberTENes Birthday Bash Guadalajara - Introducción a Argo CD
 
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
在线购买加拿大英属哥伦比亚大学毕业证本科学位证书原版一模一样
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
Artificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension FunctionsArtificia Intellicence and XPath Extension Functions
Artificia Intellicence and XPath Extension Functions
 
一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理一比一原版(USF毕业证)旧金山大学毕业证如何办理
一比一原版(USF毕业证)旧金山大学毕业证如何办理
 
Oracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptxOracle Database 19c New Features for DBAs and Developers.pptx
Oracle Database 19c New Features for DBAs and Developers.pptx
 
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian CompaniesE-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
E-Invoicing Implementation: A Step-by-Step Guide for Saudi Arabian Companies
 
fiscal year variant fiscal year variant.
fiscal year variant fiscal year variant.fiscal year variant fiscal year variant.
fiscal year variant fiscal year variant.
 
What next after learning python programming basics
What next after learning python programming basicsWhat next after learning python programming basics
What next after learning python programming basics
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Lecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptxLecture 2 - software testing SE 412.pptx
Lecture 2 - software testing SE 412.pptx
 
Webinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for EmbeddedWebinar On-Demand: Using Flutter for Embedded
Webinar On-Demand: Using Flutter for Embedded
 
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
Safelyio Toolbox Talk Softwate & App (How To Digitize Safety Meetings)
 
SQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure MalaysiaSQL Accounting Software Brochure Malaysia
SQL Accounting Software Brochure Malaysia
 

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