具有返回值的 Kotlin 协程
Kotlin Coroutines with returning value
我想创建一个具有 returning 值的协程方法。
例如)
fun funA() = async(CommonPool) {
return 1
}
fun funB() = async(CommonPool) {
return 2
}
fun sum() {
launch {
val total = funA().await() + funB().await()
}
}
如果我想return总和方法,我应该怎么做?
喜欢,
fun sum(): Int {
launch {
val total = funA().await() + funB().await()
}
return total
}
为了 return 恰好 Int
,你需要离开协程世界,这就是 runBlocking
的目的:
fun sum(): Int = runBlocking {
funA().await() + funB().await()
}
如果您想使用 sum
inside 协程,请参阅 Bridging blocking and non-blocking worlds in the coroutine guide, and Composing suspending functions 了解如何操作。
回答这个问题可能会晚一些,但希望有人会觉得它有用。下面的代码片段计算 3 个值 A + B + C 的总和。每个值在其自己的后台线程中并行独立计算,然后所有中间结果合并为一个最终结果并返回到主线程以在屏幕上显示。
所以计算最终值需要5秒(不是10秒=2+3+5)结果是6显然是非阻塞的,主线程可以在sum()执行的同时处理其他事件不完整。
suspend fun sum(scheduler: ThreadPoolExecutor): Int = coroutineScope {
withContext(scheduler.asCoroutineDispatcher()) {
val a = async { funA() }
val b = async { funB() }
val c = async { funC() }
a.await() + b.await() + c.await()
}
}
fun funA(): Int {
Thread.sleep(2000L)
return 1
}
fun funB(): Int {
Thread.sleep(3000L)
return 2
}
fun funC(): Int {
Thread.sleep(5000L)
return 3
}
class MainActivity : AppCompatActivity(), View.OnClickListener {
private val tripletsPool = ThreadPoolExecutor(3, 3, 5L, TimeUnit.SECONDS, LinkedBlockingQueue())
...
override fun onClick(view: View?) {
if (view == null) {
return
}
when (view.id) {
R.id.calculate -> {
GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT) {
progressBar.visibility = View.VISIBLE
result.setText("${sum(tripletsPool)}")
progressBar.visibility = View.GONE
}
}
}
}
}
添加另一种实现方式。
fun sum(): Int {
var sum: Int = 0
runBlocking {
val jobA = async { funA() }
val jobB = async { funB() }
runBlocking{
sum = jobA.await() + jobB.await()
}
}
return sum
}
suspend fun funA(): Int {
return 1
}
suspend fun funB(): Int {
return 2
}
我是这样做的,当试图从我的房间数据库中删除 phone 号码时,return 一个布尔值。您可以使用相同的模式来完成您想要完成的任务。在我的视图模型中:
private var parentJob = Job()
private val coroutineContext: CoroutineContext get() = parentJob + Dispatchers.Main
private val scope = CoroutineScope(coroutineContext)
suspend fun removePhoneNumber(emailSets: EmailSets, personDetails: PersonDetails) : Boolean {
var successReturn = false
scope.async(Dispatchers.IO) {
val success = async {removePhoneNumbersAsync(emailSets,personDetails)}
successReturn = success.await()
}
return successReturn
}
fun removePhoneNumbersAsync(emailSets: EmailSets, personDetails : PersonDetails):Boolean {
var success = false
try {
val emailAddressContact = EmailAddressContact(emailSets.databaseId, personDetails.id, personDetails.active)
repository.deleteEmailAddressContact(emailAddressContact)
val contact = Contact(personDetails.id, personDetails.personName, personDetails.personPhoneNumber, 0)
repository.deleteContact(contact)
success = true
} catch (exception: Exception) {
Timber.e(exception)
}
return success
}
在我的 Activity 中:
runBlocking {
if (v.tag != null) {
val personDetails = v.tag as PersonDetails
val success = viewModel.removePhoneNumber(emailSets,personDetails)
if (success) {
val parentView = v.parent as View
(parentView as? TableRow)?.visibility = View.GONE
val parentViewTable = parentView.parent as ViewGroup
(parentViewTable as? TableLayout)
parentViewTable.removeView(parentView)
}
}
}
我编辑了你的作品,我将 funA 和 funB 更改为一个挂起函数,我为求和运算符创建了一个函数,我调用了主函数,这个例子:
suspend fun funA(): Int{
return 1
}
suspend fun funB(): Int {
return 2
}
fun sum() = runBlocking{
val resultSum = async { funA.await() + funB.await() }
return resultSum
}
fun main() = runBlocking{
val result = async { sum() }
println("Your result: ${result.await()}")
}
希望对您有所帮助
这是不使用 runBlocking
.
并行 运行 funA()
和 funB()
的另一种方法
fun funA() = CoroutineScope(Dispatchers.Default).async {
delay(3000)
return@async 1
}
fun funB() = CoroutineScope(Dispatchers.Default).async {
delay(3000)
return@async 2
}
fun sum() = CoroutineScope(Dispatchers.Default).async {
val a = funA()
val b = funB()
return@async a.await() + b.await()
}
如果你想 运行 sum()
不阻塞主线程,
CoroutineScope(Dispatchers.Default).launch { // Use Dispatchers.IO for database or file I/O
measureTimeMillis {
Log.d("TAG", "sum=${sum().await()}")
}.also {
Log.d("TAG", "Completed in $it ms")
}
}
我想创建一个具有 returning 值的协程方法。
例如)
fun funA() = async(CommonPool) {
return 1
}
fun funB() = async(CommonPool) {
return 2
}
fun sum() {
launch {
val total = funA().await() + funB().await()
}
}
如果我想return总和方法,我应该怎么做?
喜欢,
fun sum(): Int {
launch {
val total = funA().await() + funB().await()
}
return total
}
为了 return 恰好 Int
,你需要离开协程世界,这就是 runBlocking
的目的:
fun sum(): Int = runBlocking {
funA().await() + funB().await()
}
如果您想使用 sum
inside 协程,请参阅 Bridging blocking and non-blocking worlds in the coroutine guide, and Composing suspending functions 了解如何操作。
回答这个问题可能会晚一些,但希望有人会觉得它有用。下面的代码片段计算 3 个值 A + B + C 的总和。每个值在其自己的后台线程中并行独立计算,然后所有中间结果合并为一个最终结果并返回到主线程以在屏幕上显示。
所以计算最终值需要5秒(不是10秒=2+3+5)结果是6显然是非阻塞的,主线程可以在sum()执行的同时处理其他事件不完整。
suspend fun sum(scheduler: ThreadPoolExecutor): Int = coroutineScope {
withContext(scheduler.asCoroutineDispatcher()) {
val a = async { funA() }
val b = async { funB() }
val c = async { funC() }
a.await() + b.await() + c.await()
}
}
fun funA(): Int {
Thread.sleep(2000L)
return 1
}
fun funB(): Int {
Thread.sleep(3000L)
return 2
}
fun funC(): Int {
Thread.sleep(5000L)
return 3
}
class MainActivity : AppCompatActivity(), View.OnClickListener {
private val tripletsPool = ThreadPoolExecutor(3, 3, 5L, TimeUnit.SECONDS, LinkedBlockingQueue())
...
override fun onClick(view: View?) {
if (view == null) {
return
}
when (view.id) {
R.id.calculate -> {
GlobalScope.launch(Dispatchers.Main, CoroutineStart.DEFAULT) {
progressBar.visibility = View.VISIBLE
result.setText("${sum(tripletsPool)}")
progressBar.visibility = View.GONE
}
}
}
}
}
添加另一种实现方式。
fun sum(): Int {
var sum: Int = 0
runBlocking {
val jobA = async { funA() }
val jobB = async { funB() }
runBlocking{
sum = jobA.await() + jobB.await()
}
}
return sum
}
suspend fun funA(): Int {
return 1
}
suspend fun funB(): Int {
return 2
}
我是这样做的,当试图从我的房间数据库中删除 phone 号码时,return 一个布尔值。您可以使用相同的模式来完成您想要完成的任务。在我的视图模型中:
private var parentJob = Job()
private val coroutineContext: CoroutineContext get() = parentJob + Dispatchers.Main
private val scope = CoroutineScope(coroutineContext)
suspend fun removePhoneNumber(emailSets: EmailSets, personDetails: PersonDetails) : Boolean {
var successReturn = false
scope.async(Dispatchers.IO) {
val success = async {removePhoneNumbersAsync(emailSets,personDetails)}
successReturn = success.await()
}
return successReturn
}
fun removePhoneNumbersAsync(emailSets: EmailSets, personDetails : PersonDetails):Boolean {
var success = false
try {
val emailAddressContact = EmailAddressContact(emailSets.databaseId, personDetails.id, personDetails.active)
repository.deleteEmailAddressContact(emailAddressContact)
val contact = Contact(personDetails.id, personDetails.personName, personDetails.personPhoneNumber, 0)
repository.deleteContact(contact)
success = true
} catch (exception: Exception) {
Timber.e(exception)
}
return success
}
在我的 Activity 中:
runBlocking {
if (v.tag != null) {
val personDetails = v.tag as PersonDetails
val success = viewModel.removePhoneNumber(emailSets,personDetails)
if (success) {
val parentView = v.parent as View
(parentView as? TableRow)?.visibility = View.GONE
val parentViewTable = parentView.parent as ViewGroup
(parentViewTable as? TableLayout)
parentViewTable.removeView(parentView)
}
}
}
我编辑了你的作品,我将 funA 和 funB 更改为一个挂起函数,我为求和运算符创建了一个函数,我调用了主函数,这个例子:
suspend fun funA(): Int{
return 1
}
suspend fun funB(): Int {
return 2
}
fun sum() = runBlocking{
val resultSum = async { funA.await() + funB.await() }
return resultSum
}
fun main() = runBlocking{
val result = async { sum() }
println("Your result: ${result.await()}")
}
希望对您有所帮助
这是不使用 runBlocking
.
funA()
和 funB()
的另一种方法
fun funA() = CoroutineScope(Dispatchers.Default).async {
delay(3000)
return@async 1
}
fun funB() = CoroutineScope(Dispatchers.Default).async {
delay(3000)
return@async 2
}
fun sum() = CoroutineScope(Dispatchers.Default).async {
val a = funA()
val b = funB()
return@async a.await() + b.await()
}
如果你想 运行 sum()
不阻塞主线程,
CoroutineScope(Dispatchers.Default).launch { // Use Dispatchers.IO for database or file I/O
measureTimeMillis {
Log.d("TAG", "sum=${sum().await()}")
}.also {
Log.d("TAG", "Completed in $it ms")
}
}