SlideShare una empresa de Scribd logo
1 de 66
Kotlin Coroutines (入門)
CHOCOTV
Louis & Timmy
Android Taipei 20181024
Topics
● Asynchronous
● suspend
● async/await
● Android
○ network
○ lifecycle
○ performance
● QA
Asynchronous
fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
}
fun getToken(userId : String) : String
fun getUserName(token : String) : String
fun sendMessage(message : String) : String
fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
}
fun getToken(userId : String) : String
fun getUserName(token : String) : String
fun sendMessage(message : String) : String
fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
}
@WorkThread
fun getToken(userId : String) : String
@WorkThread
fun getUserName(token : String) : String
fun sendMessage(message : String) : String
fun test(userId:String, callback:()->Unit){
getToken(userId) token-> {
getUserName(token) userName->{
sendMessage("User id is $userId and name is $userName"){
callback.invoke()
}
}
}
}
fun getToken(userId : String , callback:(String)->Unit)
fun getUserName(token : String , callback:(String)->Unit)
fun sendMessage(message : String , callback:(String)->Unit)
fun test(userId:String, callback:()->Unit){
getToken(userId) token-> {
getUserName(token) userName->{
sendMessage("User id is $userId and name is $userName"){
callback.invoke()
}
}
}
}
fun getToken(userId : String , callback:(String)->Unit)
fun getUserName(token : String , callback:(String)->Unit)
fun sendMessage(message : String , callback:(String)->Unit)
Callback hell
fun test(userId:String, callback:()->Unit){
getToken(userId) token-> {
getUserName(token) userName->{
sendMessage("User id is $userId and name is $userName"){
callback.invoke()
}
}
}
}
fun getToken(userId : String) : Single<String>
fun getUserName(token : String) : Single<String>
fun sendMessage(message : String)
fun test(userId:String){
getToken(userId)
.flatMap {
return@flatMap getUserName(it)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
sendMessage("User id is $userId and name is $userName")
}, {
//error handling
})
}
fun sendMessage(userId:String){
getToken(userId)
.flatMap {
return@flatMap getUserName(it)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
sendMessage("User id is $userId and name is $userName")
}, {
//error handling
})
}
fun test(userId:String){
getToken(userId)
.flatMap {
return@flatMap getUserName(it)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
sendMessage("User id is $userId and name is $userName")
}, {
//error handling
})
}
fun sendMessage(userId:String){
1. val token = getToken(userId)
2. val userName = getUserName(token)
3. sendMessage("User id is $userId and name is $userName")
}
What we want
Sequential
Suspend
suspend fun getToken(userId : String) : String
suspend fun getUserName(token : String) : String
suspend fun sendMessage(message : String) : String
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
}
suspend fun getToken(userId : String) : String {
// do request & suspend
return token
}
suspend fun getUserName(token : String) : String
suspend fun sendMessage(message : String) : String
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
suspend fun getToken(userId : String) : String
suspend fun getUserName(token : String) : String
suspend fun sendMessage(message : String)
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
}
Like Regular code !!
suspend fun getToken(userId : String) : String
suspend fun getUserName(token : String) : String
suspend fun sendMessage(message : String)
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and name is $userName")
}
Like Regular code !!
How does it work ??
Let’s get deeper
suspend fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object
fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;)Ljava/lang/String;
befroe
suspend fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object
fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;)Ljava/lang/String;
Kotlin bytecode for jvm
suspend fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object
fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;)Ljava/lang/String;
After
suspend fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object
fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;)Ljava/lang/String;
After
suspend fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object
fun getToken(userId : String) : String
public final getToken(Ljava/lang/String;)Ljava/lang/String;
Continuation-passing style
In functional programming, continuation-passing style (CPS) is a style of
programming in which control is passed explicitly in the form of a continuation
fun test( ){
val token = requestToken()
val userId = getUserId(token)
}
fun test( ){
getToken { token->
val userId = getUserId(token)
}
}
Direct Style
Continuation-passing style
In functional programming, continuation-passing style (CPS) is a style of
programming in which control is passed explicitly in the form of a continuation
fun test( ){
val token = requestToken()
val userId = getUserId(token)
}
fun test( ){
getToken { token->
val userId = getUserId(token)
}
}
Direct Style
Continuation
Continuation-passing style
In functional programming, continuation-passing style (CPS) is a style of
programming in which control is passed explicitly in the form of a continuation
fun test( ){
val token = requestToken()
val userId = getUserId(token)
}
fun test( ){
getToken { token->
val userId = getUserId(token)
}
}
Continuation-passing style
In functional programming, continuation-passing style (CPS) is a style of
programming in which control is passed explicitly in the form of a continuation
fun test( ){
val token = requestToken()
val userId = getUserId(token)
}
fun test( ){
getToken { token->
val userId = getUserId(token)
}
}
CPS == Callback
How does it work
interface Continuation<in T> {
val context: CoroutineContext
fun resume(value: T)
fun resumeWithException(exception: Throwable)
}
class test(userId:String , sm : Continuation<Unit>) : Any{
val sm = CoroutineImpl {
fun doResume(...){
test(null,this)
}
var token : String
var userName : String
}
switch(sm.Label){
case 0:
sm.Label = 1
getToken(userId,sm)
break
case 1:
sm.Label = 2
getUserName(sm.token , sm)
break
case 2:
sm.Label = 3
sendMessage("User id is $userId and name is $userName")
break
}
}
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and
name is $userName")
}
class test(userId:String , callback : Continuation<Unit>) : Any{
val sm = CoroutineImpl {
fun resume(...){
test(null,this)
}
var token : String
var userName : String
}
switch(sm.Label){
case 0:
sm.Label = 1
getToken(userId,sm)
break
case 1:
sm.Label = 2
getUserName(sm.token , sm)
break
case 2:
sm.Label = 3
sendMessage("User id is $userId and name is $userName")
break
}
}
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and
name is $userName")
}
class test(userId:String , callback : Continuation<Unit>) : Any{
val sm = CoroutineImpl {
fun doResume(...){
test(null,this)
}
var token : String
var userName : String
}
switch(sm.Label){
case 0:
sm.Label = 1
getToken(userId,sm)
break
case 1:
sm.Label = 2
getUserName(sm.token , sm)
break
case 2:
sm.Label = 3
sendMessage("User id is $userId and name is $userName")
break
}
}
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and
name is $userName")
}
class test(userId:String , callback : Continuation<Unit>) : Any{
val sm = CoroutineImpl {
fun doResume(...){
test(null,this)
}
var token : String
var userName : String
}
switch(sm.Label){
case 0:
sm.Label = 1
getToken(userId,sm)
break
case 1:
sm.Label = 2
getUserName(sm.token , sm)
break
case 2:
sm.Label = 3
sendMessage("User id is $userId and name is $userName")
break
}
}
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and
name is $userName")
}
spending function
class test(userId:String , callback : Continuation<Unit>) : Any{
val sm = CoroutineImpl {
fun doResume(...){
test(null,this)
}
var token : String
var userName : String
}
switch(sm.Label){
case 0:
sm.Label = 1
getToken(userId, sm )
break
case 1:
sm.Label = 2
getUserName(sm.token , sm)
break
case 2:
sm.Label = 3
sendMessage("User id is $userId and name is $userName")
break
}
}
suspend fun test(userId:String){
val token = getToken(userId)
val userName = getUserName(token)
sendMessage("User id is $userId and
name is $userName")
}
Restore state
class test(userId:String , callback : Continuation<Unit>) : Any{
val sm = CoroutineImpl {
fun resume(...){
test(null,this)
}
var token : String
var userName : String
}
switch(sm.Label){
case 0:
sm.Label = 1
getToken(userId,sm)
break
case 1:
sm.Label = 2
getUserName(sm.token , sm)
break
case 2:
sm.Label = 3
sendMessage("User id is $userId and name is $userName")
break
}
}
suspend fun test(userId:String){
val token = getToken(userId)
val userName =
getUserName(token)
sendMessage("User id is $userId
and name is $userName")
}
Android
Retrofit
kotlin version 1.3
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
kotlin version pre-1.3
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0'
val retrofit = Retrofit.Builder()
.baseUrl("https://example.com/")
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.build()
Retrofit
interface MyService {
@GET("/user")
fun getUser(): Deferred<User>
}
Retrofit
interface MyService {
@GET("/user")
fun getUser(): Deferred<User>
}
Retrofit
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser()
withContext(Dispatchers.Main) {
showMesssgae(data.await().message)
}
}
Retrofit
interface MyService {
@GET("/user")
fun getUser(): Call<User>
}
Retrofit
suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation {
if (cont.isCancelled) {
cont.cancel()
}
}
enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>?, t: Throwable) {
cont.resumeWithException(t)
}
override fun onResponse(call: Call<T>?, response: Response<T>) {
if (response.isSuccessful) {
val body = response.body()
?: return cont.resumeWithException(NullPointerException())
cont.resume(body)
} else {
cont.resumeWithException(HttpException(response))
}
}
})
}
Retrofit
suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation {
if (cont.isCancelled) {
cont.cancel()
}
}
enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>?, t: Throwable) {
cont.resumeWithException(t)
}
override fun onResponse(call: Call<T>?, response: Response<T>) {
if (response.isSuccessful) {
val body = response.body()
?: return cont.resumeWithException(NullPointerException())
cont.resume(body)
} else {
cont.resumeWithException(HttpException(response))
}
}
})
}
Retrofit
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser().await()
withContext(Dispatchers.Main) {
showMesssgae(data.message)
}
}
Retrofit
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser().await()
withContext(Dispatchers.Main) {
showMesssgae(data.message)
}
}
// Call<T>.await is extension function retrun data
Error handling
GlobalScope.launch(Dispatchers.IO) {
try {
val data = APIRepo.getUser()
withContext(Dispatchers.Main) {
showMesssgae(data.message)
}
}catch(e : Exception){
// error
}
}
How to cancel ?
val job = GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser()
withContext(Dispatchers.Main) {
showMesssgae(data.message)
}
}
job.cancel()
// RxJava Disposable
How to cancel ?
job.cancel()
Job Job …….. n
class MainActivityTest : AppCompatActivity(),
CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Main
override fun onDestroy() {
super.onDestroy()
job.cancel()
}
GlobalScope.launch(coroutineContext)
{
//do async
}
GlobalScope.launch(coroutineContext) {
//do async
}
GlobalScope.launch(coroutineContext) {
//do async
}
Concurrently
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser() // Deferred
withContext(Dispatchers.Main) {
showMesssgae(data.await().message)
}
}
Concurrently
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser() // Deferred
val dataNew = APIRepo.getUserNew() // Deferred
val dataNewTwo = APIRepo.getUserNewTwo() // Deferred
withContext(Dispatchers.Main) {
showMesssgae(data.await().message)
}
}
Concurrently
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser() // Deferred
val dataNew = APIRepo.getUserNew() // Deferred
val dataNewTwo = APIRepo.getUserNewTwo() // Deferred
withContext(Dispatchers.Main) {
showMesssgae(data.await().message)
}
}
Concurrently
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser() // Deferred
val dataNew = APIRepo.getUserNew() // Deferred
val dataNewTwo = APIRepo.getUserNewTwo() // Deferred
withContext(Dispatchers.Main) {
showMesssgae(data.await().message,dataNew.await().message,dataNewTwo.await().message)
}
}
Performance
Reference :
https://proandroiddev.com/kotlin-coroutines-vs-rxjava-an-initial-performance-test-68160cfc6723
GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser() // Deferred
withContext(Dispatchers.Main) {
showMesssgae(data.await().message)
}
}
Recap
● Asynchronous
● Apk Siz & Method count
● Performance
● Readable
● Cost
Recap
● Asynchronous
● Apk size & Method count
● Performance
● Readable
● Cost
Recap
● Asynchronous
● Apk Siz & Method count
● Performance
● Readable
● Cost
Recap
● Asynchronous
● Apk Siz & Method count
● Performance
● Readable
● Cost
Recap
● Asynchronous
● Apk Siz & Method count
● Performance
● Readable
● Cost
Q & A
Thank you
Reference
https://kotlinlang.org/docs/reference/coroutines-overview.html
https://www.youtube.com/watch?v=_hfBv0a09Jc
https://www.youtube.com/watch?v=YrrUCSi72E8&t=707s

Más contenido relacionado

La actualidad más candente

The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212Mahmoud Samir Fayed
 
Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Roman Elizarov
 
FRP: What does "declarative" mean
FRP: What does "declarative" meanFRP: What does "declarative" mean
FRP: What does "declarative" meanPeter Ovchinnikov
 
Groovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトークGroovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトークTsuyoshi Yamamoto
 
Broken windows de práticas ágeis
Broken windows de práticas ágeisBroken windows de práticas ágeis
Broken windows de práticas ágeisCecilia Fernandes
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and InferenceRichard Fox
 
PyTrening 2.0 # 15 Okienka GUI
PyTrening 2.0 # 15 Okienka GUIPyTrening 2.0 # 15 Okienka GUI
PyTrening 2.0 # 15 Okienka GUIMoniaJ
 
Python Asíncrono - Async Python
Python Asíncrono - Async PythonPython Asíncrono - Async Python
Python Asíncrono - Async PythonJavier Abadía
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Baruch Sadogursky
 
اسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونیاسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونیMohammad Reza Kamalifard
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveEleanor McHugh
 
Distributed Data Structures
Distributed Data StructuresDistributed Data Structures
Distributed Data StructuresPDX Web & Design
 
4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz
4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz
4Developers 2015: Testowanie ze Spockiem - Dominik PrzybyszPROIDEA
 
The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88Mahmoud Samir Fayed
 

La actualidad más candente (20)

Lập trình Python cơ bản
Lập trình Python cơ bảnLập trình Python cơ bản
Lập trình Python cơ bản
 
The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212The Ring programming language version 1.10 book - Part 56 of 212
The Ring programming language version 1.10 book - Part 56 of 212
 
Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017Fresh Async with Kotlin @ QConSF 2017
Fresh Async with Kotlin @ QConSF 2017
 
FRP: What does "declarative" mean
FRP: What does "declarative" meanFRP: What does "declarative" mean
FRP: What does "declarative" mean
 
Groovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトークGroovy ネタ NGK 忘年会2009 ライトニングトーク
Groovy ネタ NGK 忘年会2009 ライトニングトーク
 
DDS-20m
DDS-20mDDS-20m
DDS-20m
 
Broken windows de práticas ágeis
Broken windows de práticas ágeisBroken windows de práticas ágeis
Broken windows de práticas ágeis
 
Generics and Inference
Generics and InferenceGenerics and Inference
Generics and Inference
 
Voce Tem Orgulho Do Seu Codigo
Voce Tem Orgulho Do Seu CodigoVoce Tem Orgulho Do Seu Codigo
Voce Tem Orgulho Do Seu Codigo
 
PyTrening 2.0 # 15 Okienka GUI
PyTrening 2.0 # 15 Okienka GUIPyTrening 2.0 # 15 Okienka GUI
PyTrening 2.0 # 15 Okienka GUI
 
Python Asíncrono - Async Python
Python Asíncrono - Async PythonPython Asíncrono - Async Python
Python Asíncrono - Async Python
 
PureScript & Pux
PureScript & PuxPureScript & Pux
PureScript & Pux
 
Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
اسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونیاسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونی
اسلاید اول جلسه چهارم کلاس پایتون برای هکرهای قانونی
 
Message
MessageMessage
Message
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
Distributed Data Structures
Distributed Data StructuresDistributed Data Structures
Distributed Data Structures
 
4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz
4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz
4Developers 2015: Testowanie ze Spockiem - Dominik Przybysz
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88
 

Similar a Kotlin coroutines

Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Chang W. Doh
 
First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesNebojša Vukšić
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드NAVER Engineering
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kirill Rozov
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard LibraryNelson Glauber Leal
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à DartSOAT
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kirill Rozov
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlinintelliyole
 
iOS Talks 1 - CodeCamp Osijek - Swift u praksi
iOS Talks 1 - CodeCamp Osijek - Swift u praksiiOS Talks 1 - CodeCamp Osijek - Swift u praksi
iOS Talks 1 - CodeCamp Osijek - Swift u praksiMarin Benčević
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»e-Legion
 
Server Side Swift with Swag
Server Side Swift with SwagServer Side Swift with Swag
Server Side Swift with SwagJens Ravens
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewDmytro Zaitsev
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.UA Mobile
 
About java
About javaAbout java
About javaJay Xu
 
つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版kamedon39
 
Finagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ KnoldusFinagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ KnoldusKnoldus Inc.
 

Similar a Kotlin coroutines (20)

Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가Kotlin의 코루틴은 어떻게 동작하는가
Kotlin의 코루틴은 어떻게 동작하는가
 
First few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examplesFirst few months with Kotlin - Introduction through android examples
First few months with Kotlin - Introduction through android examples
 
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
Introduction kot iin
Introduction kot iinIntroduction kot iin
Introduction kot iin
 
Controle de estado
Controle de estadoControle de estado
Controle de estado
 
Introduction à Dart
Introduction à DartIntroduction à Dart
Introduction à Dart
 
Kotlin
KotlinKotlin
Kotlin
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
Php sql-android
Php sql-androidPhp sql-android
Php sql-android
 
Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
iOS Talks 1 - CodeCamp Osijek - Swift u praksi
iOS Talks 1 - CodeCamp Osijek - Swift u praksiiOS Talks 1 - CodeCamp Osijek - Swift u praksi
iOS Talks 1 - CodeCamp Osijek - Swift u praksi
 
Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»Юрий Буянов «Squeryl — ORM с человеческим лицом»
Юрий Буянов «Squeryl — ORM с человеческим лицом»
 
Server Side Swift with Swag
Server Side Swift with SwagServer Side Swift with Swag
Server Side Swift with Swag
 
Coroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth reviewCoroutines in Kotlin. In-depth review
Coroutines in Kotlin. In-depth review
 
Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.Coroutines in Kotlin. UA Mobile 2017.
Coroutines in Kotlin. UA Mobile 2017.
 
About java
About javaAbout java
About java
 
つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版つくってあそぼ Kotlin DSL 第2版
つくってあそぼ Kotlin DSL 第2版
 
Finagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ KnoldusFinagle By Twitter Engineer @ Knoldus
Finagle By Twitter Engineer @ Knoldus
 

Más de TSE-JU LIN(Louis)

Android instant apps, step by-step: how CHOCOTV went about it
Android instant apps, step by-step: how CHOCOTV went about itAndroid instant apps, step by-step: how CHOCOTV went about it
Android instant apps, step by-step: how CHOCOTV went about itTSE-JU LIN(Louis)
 
20160929 android taipei Sonatype nexus on amazon ec2
20160929 android taipei Sonatype nexus on amazon ec2 20160929 android taipei Sonatype nexus on amazon ec2
20160929 android taipei Sonatype nexus on amazon ec2 TSE-JU LIN(Louis)
 

Más de TSE-JU LIN(Louis) (7)

Mulit cdn exoplayer
Mulit cdn exoplayerMulit cdn exoplayer
Mulit cdn exoplayer
 
Android instant apps, step by-step: how CHOCOTV went about it
Android instant apps, step by-step: how CHOCOTV went about itAndroid instant apps, step by-step: how CHOCOTV went about it
Android instant apps, step by-step: how CHOCOTV went about it
 
Chromecast v3
Chromecast v3Chromecast v3
Chromecast v3
 
Exoplayer 2
Exoplayer  2Exoplayer  2
Exoplayer 2
 
2017.03.20 android taipei
2017.03.20 android taipei2017.03.20 android taipei
2017.03.20 android taipei
 
2017.02.22 android taipei
2017.02.22 android taipei2017.02.22 android taipei
2017.02.22 android taipei
 
20160929 android taipei Sonatype nexus on amazon ec2
20160929 android taipei Sonatype nexus on amazon ec2 20160929 android taipei Sonatype nexus on amazon ec2
20160929 android taipei Sonatype nexus on amazon ec2
 

Último

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Victor Rentea
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMKumar Satyam
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKJago de Vreede
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAnitaRaj43
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...apidays
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...Zilliz
 

Último (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 

Kotlin coroutines

  • 1. Kotlin Coroutines (入門) CHOCOTV Louis & Timmy Android Taipei 20181024
  • 2. Topics ● Asynchronous ● suspend ● async/await ● Android ○ network ○ lifecycle ○ performance ● QA
  • 4.
  • 5. fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } fun getToken(userId : String) : String fun getUserName(token : String) : String fun sendMessage(message : String) : String
  • 6. fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } fun getToken(userId : String) : String fun getUserName(token : String) : String fun sendMessage(message : String) : String
  • 7. fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } @WorkThread fun getToken(userId : String) : String @WorkThread fun getUserName(token : String) : String fun sendMessage(message : String) : String
  • 8. fun test(userId:String, callback:()->Unit){ getToken(userId) token-> { getUserName(token) userName->{ sendMessage("User id is $userId and name is $userName"){ callback.invoke() } } } } fun getToken(userId : String , callback:(String)->Unit) fun getUserName(token : String , callback:(String)->Unit) fun sendMessage(message : String , callback:(String)->Unit)
  • 9. fun test(userId:String, callback:()->Unit){ getToken(userId) token-> { getUserName(token) userName->{ sendMessage("User id is $userId and name is $userName"){ callback.invoke() } } } } fun getToken(userId : String , callback:(String)->Unit) fun getUserName(token : String , callback:(String)->Unit) fun sendMessage(message : String , callback:(String)->Unit) Callback hell
  • 10. fun test(userId:String, callback:()->Unit){ getToken(userId) token-> { getUserName(token) userName->{ sendMessage("User id is $userId and name is $userName"){ callback.invoke() } } } } fun getToken(userId : String) : Single<String> fun getUserName(token : String) : Single<String> fun sendMessage(message : String)
  • 11. fun test(userId:String){ getToken(userId) .flatMap { return@flatMap getUserName(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ sendMessage("User id is $userId and name is $userName") }, { //error handling }) }
  • 12. fun sendMessage(userId:String){ getToken(userId) .flatMap { return@flatMap getUserName(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ sendMessage("User id is $userId and name is $userName") }, { //error handling }) }
  • 13. fun test(userId:String){ getToken(userId) .flatMap { return@flatMap getUserName(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ sendMessage("User id is $userId and name is $userName") }, { //error handling }) }
  • 14. fun sendMessage(userId:String){ 1. val token = getToken(userId) 2. val userName = getUserName(token) 3. sendMessage("User id is $userId and name is $userName") } What we want Sequential
  • 15. Suspend suspend fun getToken(userId : String) : String suspend fun getUserName(token : String) : String suspend fun sendMessage(message : String) : String suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") }
  • 16. suspend fun getToken(userId : String) : String { // do request & suspend return token } suspend fun getUserName(token : String) : String suspend fun sendMessage(message : String) : String suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName")
  • 17. suspend fun getToken(userId : String) : String suspend fun getUserName(token : String) : String suspend fun sendMessage(message : String) suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } Like Regular code !!
  • 18. suspend fun getToken(userId : String) : String suspend fun getUserName(token : String) : String suspend fun sendMessage(message : String) suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } Like Regular code !!
  • 19.
  • 20. How does it work ??
  • 22. suspend fun getToken(userId : String) : String public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object fun getToken(userId : String) : String public final getToken(Ljava/lang/String;)Ljava/lang/String; befroe
  • 23. suspend fun getToken(userId : String) : String public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object fun getToken(userId : String) : String public final getToken(Ljava/lang/String;)Ljava/lang/String; Kotlin bytecode for jvm
  • 24. suspend fun getToken(userId : String) : String public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object fun getToken(userId : String) : String public final getToken(Ljava/lang/String;)Ljava/lang/String; After
  • 25. suspend fun getToken(userId : String) : String public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object fun getToken(userId : String) : String public final getToken(Ljava/lang/String;)Ljava/lang/String; After
  • 26. suspend fun getToken(userId : String) : String public final getToken(Ljava/lang/String;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object fun getToken(userId : String) : String public final getToken(Ljava/lang/String;)Ljava/lang/String;
  • 27. Continuation-passing style In functional programming, continuation-passing style (CPS) is a style of programming in which control is passed explicitly in the form of a continuation fun test( ){ val token = requestToken() val userId = getUserId(token) } fun test( ){ getToken { token-> val userId = getUserId(token) } } Direct Style
  • 28. Continuation-passing style In functional programming, continuation-passing style (CPS) is a style of programming in which control is passed explicitly in the form of a continuation fun test( ){ val token = requestToken() val userId = getUserId(token) } fun test( ){ getToken { token-> val userId = getUserId(token) } } Direct Style Continuation
  • 29. Continuation-passing style In functional programming, continuation-passing style (CPS) is a style of programming in which control is passed explicitly in the form of a continuation fun test( ){ val token = requestToken() val userId = getUserId(token) } fun test( ){ getToken { token-> val userId = getUserId(token) } }
  • 30. Continuation-passing style In functional programming, continuation-passing style (CPS) is a style of programming in which control is passed explicitly in the form of a continuation fun test( ){ val token = requestToken() val userId = getUserId(token) } fun test( ){ getToken { token-> val userId = getUserId(token) } } CPS == Callback
  • 31. How does it work interface Continuation<in T> { val context: CoroutineContext fun resume(value: T) fun resumeWithException(exception: Throwable) }
  • 32. class test(userId:String , sm : Continuation<Unit>) : Any{ val sm = CoroutineImpl { fun doResume(...){ test(null,this) } var token : String var userName : String } switch(sm.Label){ case 0: sm.Label = 1 getToken(userId,sm) break case 1: sm.Label = 2 getUserName(sm.token , sm) break case 2: sm.Label = 3 sendMessage("User id is $userId and name is $userName") break } } suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") }
  • 33. class test(userId:String , callback : Continuation<Unit>) : Any{ val sm = CoroutineImpl { fun resume(...){ test(null,this) } var token : String var userName : String } switch(sm.Label){ case 0: sm.Label = 1 getToken(userId,sm) break case 1: sm.Label = 2 getUserName(sm.token , sm) break case 2: sm.Label = 3 sendMessage("User id is $userId and name is $userName") break } } suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") }
  • 34. class test(userId:String , callback : Continuation<Unit>) : Any{ val sm = CoroutineImpl { fun doResume(...){ test(null,this) } var token : String var userName : String } switch(sm.Label){ case 0: sm.Label = 1 getToken(userId,sm) break case 1: sm.Label = 2 getUserName(sm.token , sm) break case 2: sm.Label = 3 sendMessage("User id is $userId and name is $userName") break } } suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") }
  • 35. class test(userId:String , callback : Continuation<Unit>) : Any{ val sm = CoroutineImpl { fun doResume(...){ test(null,this) } var token : String var userName : String } switch(sm.Label){ case 0: sm.Label = 1 getToken(userId,sm) break case 1: sm.Label = 2 getUserName(sm.token , sm) break case 2: sm.Label = 3 sendMessage("User id is $userId and name is $userName") break } } suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } spending function
  • 36. class test(userId:String , callback : Continuation<Unit>) : Any{ val sm = CoroutineImpl { fun doResume(...){ test(null,this) } var token : String var userName : String } switch(sm.Label){ case 0: sm.Label = 1 getToken(userId, sm ) break case 1: sm.Label = 2 getUserName(sm.token , sm) break case 2: sm.Label = 3 sendMessage("User id is $userId and name is $userName") break } } suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") } Restore state
  • 37. class test(userId:String , callback : Continuation<Unit>) : Any{ val sm = CoroutineImpl { fun resume(...){ test(null,this) } var token : String var userName : String } switch(sm.Label){ case 0: sm.Label = 1 getToken(userId,sm) break case 1: sm.Label = 2 getUserName(sm.token , sm) break case 2: sm.Label = 3 sendMessage("User id is $userId and name is $userName") break } } suspend fun test(userId:String){ val token = getToken(userId) val userName = getUserName(token) sendMessage("User id is $userId and name is $userName") }
  • 39. Retrofit kotlin version 1.3 implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' kotlin version pre-1.3 implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-experimental-adapter:1.0.0' val retrofit = Retrofit.Builder() .baseUrl("https://example.com/") .addCallAdapterFactory(CoroutineCallAdapterFactory()) .build()
  • 42. Retrofit GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() withContext(Dispatchers.Main) { showMesssgae(data.await().message) } }
  • 44. Retrofit suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont -> cont.invokeOnCancellation { if (cont.isCancelled) { cont.cancel() } } enqueue(object : Callback<T> { override fun onFailure(call: Call<T>?, t: Throwable) { cont.resumeWithException(t) } override fun onResponse(call: Call<T>?, response: Response<T>) { if (response.isSuccessful) { val body = response.body() ?: return cont.resumeWithException(NullPointerException()) cont.resume(body) } else { cont.resumeWithException(HttpException(response)) } } }) }
  • 45. Retrofit suspend fun <T> Call<T>.await(): T = suspendCancellableCoroutine { cont -> cont.invokeOnCancellation { if (cont.isCancelled) { cont.cancel() } } enqueue(object : Callback<T> { override fun onFailure(call: Call<T>?, t: Throwable) { cont.resumeWithException(t) } override fun onResponse(call: Call<T>?, response: Response<T>) { if (response.isSuccessful) { val body = response.body() ?: return cont.resumeWithException(NullPointerException()) cont.resume(body) } else { cont.resumeWithException(HttpException(response)) } } }) }
  • 46. Retrofit GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser().await() withContext(Dispatchers.Main) { showMesssgae(data.message) } }
  • 47. Retrofit GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser().await() withContext(Dispatchers.Main) { showMesssgae(data.message) } } // Call<T>.await is extension function retrun data
  • 48. Error handling GlobalScope.launch(Dispatchers.IO) { try { val data = APIRepo.getUser() withContext(Dispatchers.Main) { showMesssgae(data.message) } }catch(e : Exception){ // error } }
  • 49. How to cancel ? val job = GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() withContext(Dispatchers.Main) { showMesssgae(data.message) } } job.cancel() // RxJava Disposable
  • 50. How to cancel ? job.cancel()
  • 51. Job Job …….. n class MainActivityTest : AppCompatActivity(), CoroutineScope { private val job = Job() override val coroutineContext: CoroutineContext get() = job + Dispatchers.Main override fun onDestroy() { super.onDestroy() job.cancel() } GlobalScope.launch(coroutineContext) { //do async } GlobalScope.launch(coroutineContext) { //do async } GlobalScope.launch(coroutineContext) { //do async }
  • 52. Concurrently GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() // Deferred withContext(Dispatchers.Main) { showMesssgae(data.await().message) } }
  • 53. Concurrently GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() // Deferred val dataNew = APIRepo.getUserNew() // Deferred val dataNewTwo = APIRepo.getUserNewTwo() // Deferred withContext(Dispatchers.Main) { showMesssgae(data.await().message) } }
  • 54. Concurrently GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() // Deferred val dataNew = APIRepo.getUserNew() // Deferred val dataNewTwo = APIRepo.getUserNewTwo() // Deferred withContext(Dispatchers.Main) { showMesssgae(data.await().message) } }
  • 55. Concurrently GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() // Deferred val dataNew = APIRepo.getUserNew() // Deferred val dataNewTwo = APIRepo.getUserNewTwo() // Deferred withContext(Dispatchers.Main) { showMesssgae(data.await().message,dataNew.await().message,dataNewTwo.await().message) } }
  • 58. GlobalScope.launch(Dispatchers.IO) { val data = APIRepo.getUser() // Deferred withContext(Dispatchers.Main) { showMesssgae(data.await().message) } }
  • 59.
  • 60. Recap ● Asynchronous ● Apk Siz & Method count ● Performance ● Readable ● Cost
  • 61. Recap ● Asynchronous ● Apk size & Method count ● Performance ● Readable ● Cost
  • 62. Recap ● Asynchronous ● Apk Siz & Method count ● Performance ● Readable ● Cost
  • 63. Recap ● Asynchronous ● Apk Siz & Method count ● Performance ● Readable ● Cost
  • 64. Recap ● Asynchronous ● Apk Siz & Method count ● Performance ● Readable ● Cost
  • 65. Q & A Thank you

Notas del editor

  1. 分享自己入門的經驗 why coroountines ? What’s the goal ? What’s the problem want fix ? Reduce apk size Both method count & size smaller 10~20% than RxJava 輕量化的Thread 在編碼階段做到Thread的management 寫同步的Code卻可以讓你處理異步的事情 因為看到最近的文章影片都在說關於這個概念的東西,因而開始使用
  2. 我們都知道在一個應用程式的開始,Android給予這個process一個Thread用於渲染畫面, 所以如果今天 出現了一些工作 會搶佔這個Thread(Blocking thread) 打亂本來在做渲染thread的步調的時候. 我們必須要在調用新的worker thread 也就是所謂的Asynchronous的概念
  3. 解釋同步異步的差異 針對Async的處理, android 官方也提供一些庫,也有些標準的作法
  4. 解釋這是一個step by step 的simple case It just a simple code , concept
  5. Every step is depend on last stept 相互依賴 getToken 假設給予userId可以拿到token getUserName inpu token can get user name Last step is just print the userid & usaname
  6. But what if the case going to a liitl bit different When getToken this method need to create new thread witch mean workThread to do async also the getUserName need it too The last step also print message
  7. The first way in my mind is using callback ,
  8. 如果我想要我的code就可讀性而言,他就要像dirct code 一樣 1 2 3 依序完成
  9. 首先看到Test fun 在編碼階段 產生Countinuation 的 input callback 沒有問題
  10. 再來 sm 代表著 Countinuation的實例 , 裡面包含 resume() 以及產生 這個fun內 會有的token & username 的參數
  11. 最後就是到底怎麼運行的
  12. 跟callback的差別
  13. 這可能也是大家關注的議題之一 Why should i need this What’s new about performance in Kotlin coroutines
  14. Dispatchers 是可以指定 IO Main Executes
  15. 對於Defalut他背後的實踐是ForJoin pool
  16. Why coroutines? Async task RxJava Call back Thread Thread Pool
  17. If you guys consider about Apk szie & method count 10% ~ 20% reduce apk size
  18. 如果每一次的Async就起一個Thread 所以可能會用Thread pool or AsyncTask 如果想要在code的整體結構 更清楚明瞭 不抹殺掉切換Thread的作法當然是RxJava 但如果就corountines dispatcher的觀點看,他背後也指示指向一個Thread pool 只不過他是ForJoinPool對於多個Task的指派可以更有效率的完成 , 你也可以起一個ForJoinPool不使用coroutines的framework去處理task 但就callback hell的觀點 之前也提到 一個coroutines的scope都只會共用一個continution , 相較於多個callback的回傳 少了不少object對於系統的負擔
  19. 如果每一次的Async就起一個Thread 所以可能會用Thread pool or AsyncTask 如果想要在code的整體結構 更清楚明瞭 不抹殺掉切換Thread的作法當然是RxJava 但如果就corountines dispatcher的觀點看,他背後也指示指向一個Thread pool 只不過他是ForJoinPool對於多個Task的指派可以更有效率的完成 , 你也可以起一個ForJoinPool不使用coroutines的framework去處理task 但就callback hell的觀點 之前也提到 一個coroutines的scope都只會共用一個continution , 相較於多個callback的回傳 少了不少object對於系統的負擔