在 kotlin 协程中实现 async-await()
Implementing async- await() in kotlin coroutine
我创建了如下函数:
fun getPercentage(id:String): String {
var percentage=""
scope.launch {
percentage=repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value >>","$$$ value >>"+percentage)
}
Log.e("$$$ value outside >>","$$$ value >>"+percentage)
return percenatge
}
在这里,我不能return使用变量更新值:百分比。
我得到的日志如下:
$$$ value outside >>
$$$ value >> 50
表示我无法 return 最新值。流程出了点问题。
有人建议我使用 async{} 和 await()。但我不知道这对这里有什么帮助?
请指导。谢谢
launch函数在后台启动协程,然后继续。因此,您的“外部”代码在“内部”协程完成之前 运行。
使用协程中的async function instead to return a Deferred值:
fun getPercentage(id:String): Deferred<String> {
return scope.async {
percentage=repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value >>","$$$ value >>"+percentage)
}
}
当然要注意的是,你更有可能想把getPercentage
做成一个挂起函数,然后直接调用await
:
suspend fun getPercentage(id:String): String {
val percentageDeferred = scope.async {
percentage=repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value >>","$$$ value >>"+percentage)
}
val percentage = percentageDeferred.await()
Log.e("$$$ value outside >>","$$$ value >>"+percentage)
return percentage
}
您也可能想在 await
之前执行其他操作,否则您最好也将 repo.getPercentage
设为挂起函数,然后直接调用它:
suspend fun getPercentage(id:String): String {
// if repo.getPercentage is a suspend function, this call suspends
// like the await in the previous example
val percentage = repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value outside >>","$$$ value >>"+percentage)
return percentage
}
请参阅 Kotlin 文档中的 Concurrent using async。
我认为您不一定需要在这种情况下使用异步,尤其是。您只需要知道 launch { ... }
中的任何内容都是异步执行的。所以到 getPercentage
returns 时,您的协程可能还没有启动。
记住这一点,我相信您可能想要更改代码的工作方式。在不更改签名的情况下使 fun getPercentage(id: String): String
工作的唯一方法是将 scope.launch { ... }
替换为 scope.runBlocking { ... }
,但您可能不想这样做,因为它会阻塞您的线程。
相反,您可以将 getPercentage
更改为 suspend
方法:
suspend fun getPercentage(id: String): String {
return repo.getPercentage(id)?.get(0)?.percent.toString()
}
但是,suspend
方法只能从协程内部调用。所以你需要这样称呼它:
scope.launch {
val percentage = getPercentage("some ID")
// Now you can use `percentage` for whatever you need.
}
我创建了如下函数:
fun getPercentage(id:String): String {
var percentage=""
scope.launch {
percentage=repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value >>","$$$ value >>"+percentage)
}
Log.e("$$$ value outside >>","$$$ value >>"+percentage)
return percenatge
}
在这里,我不能return使用变量更新值:百分比。
我得到的日志如下:
$$$ value outside >>
$$$ value >> 50
表示我无法 return 最新值。流程出了点问题。
有人建议我使用 async{} 和 await()。但我不知道这对这里有什么帮助?
请指导。谢谢
launch函数在后台启动协程,然后继续。因此,您的“外部”代码在“内部”协程完成之前 运行。
使用协程中的async function instead to return a Deferred值:
fun getPercentage(id:String): Deferred<String> {
return scope.async {
percentage=repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value >>","$$$ value >>"+percentage)
}
}
当然要注意的是,你更有可能想把getPercentage
做成一个挂起函数,然后直接调用await
:
suspend fun getPercentage(id:String): String {
val percentageDeferred = scope.async {
percentage=repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value >>","$$$ value >>"+percentage)
}
val percentage = percentageDeferred.await()
Log.e("$$$ value outside >>","$$$ value >>"+percentage)
return percentage
}
您也可能想在 await
之前执行其他操作,否则您最好也将 repo.getPercentage
设为挂起函数,然后直接调用它:
suspend fun getPercentage(id:String): String {
// if repo.getPercentage is a suspend function, this call suspends
// like the await in the previous example
val percentage = repo.getPercentage(id)?.get(0)?.percent.toString()
Log.e("$$$ value outside >>","$$$ value >>"+percentage)
return percentage
}
请参阅 Kotlin 文档中的 Concurrent using async。
我认为您不一定需要在这种情况下使用异步,尤其是。您只需要知道 launch { ... }
中的任何内容都是异步执行的。所以到 getPercentage
returns 时,您的协程可能还没有启动。
记住这一点,我相信您可能想要更改代码的工作方式。在不更改签名的情况下使 fun getPercentage(id: String): String
工作的唯一方法是将 scope.launch { ... }
替换为 scope.runBlocking { ... }
,但您可能不想这样做,因为它会阻塞您的线程。
相反,您可以将 getPercentage
更改为 suspend
方法:
suspend fun getPercentage(id: String): String {
return repo.getPercentage(id)?.get(0)?.percent.toString()
}
但是,suspend
方法只能从协程内部调用。所以你需要这样称呼它:
scope.launch {
val percentage = getPercentage("some ID")
// Now you can use `percentage` for whatever you need.
}