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)
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 !!
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")
}
49. How to cancel ?
val job = GlobalScope.launch(Dispatchers.IO) {
val data = APIRepo.getUser()
withContext(Dispatchers.Main) {
showMesssgae(data.message)
}
}
job.cancel()
// RxJava Disposable
解釋這是一個step by step 的simple case
It just a simple code , concept
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
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
The first way in my mind is using callback ,
如果我想要我的code就可讀性而言,他就要像dirct code 一樣
1 2 3 依序完成
首先看到Test fun 在編碼階段 產生Countinuation 的 input callback 沒有問題