我想创建一个具有返回值的协程方法。
例如)
fun funA() = async(CommonPool) {
return 1
}
fun funB() = async(CommonPool) {
return 2
}
fun sum() {
launch {
val total = funA().await() + funB().await()
}
}
如果我想以总和方式返回总数,我该怎么做?
等
fun sum(): Int {
launch {
val total = funA().await() + funB().await()
}
return total
}
答案 0 :(得分:11)
要准确返回Int
,您需要离开协程世界,这就是runBlocking
的用途:
fun sum(): Int = runBlocking {
funA().await() + funB().await()
}
如果您想在协同程序中使用sum
,请参阅协程指南中的Bridging blocking and non-blocking worlds和Composing suspending functions,了解如何操作。
答案 1 :(得分:2)
回答这个问题可能为时已晚,但希望有人会发现它有用。下面的代码段计算了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
}
}
}
}
}
答案 2 :(得分:2)
添加另一种实现方法。
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
}
答案 3 :(得分:0)
这是我这样做的方法,当尝试从Room数据库中删除电话号码时返回一个布尔值。您可以为要完成的任务使用相同的模式。在我的视图模型中:
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
}
在我的活动中:
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)
}
}
}
答案 4 :(得分:0)
我编辑您的工作,将funA和funB更改为暂停函数,并为sum运算符创建了一个函数,然后调用main函数,此示例:
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()}")
}
希望这会有所帮助
答案 5 :(得分:0)
这是另一种无需使用funA()
即可并行运行funB()
和runBlocking
的方法。
fun funA() = CoroutineScope(Dispatchers.IO).async {
delay(3000)
return@async 1
}
fun funB() = CoroutineScope(Dispatchers.IO).async {
delay(3000)
return@async 2
}
fun sum() = CoroutineScope(Dispatchers.IO).async {
val a = funA()
val b = funB()
return@async a.await() + b.await()
}
如果您想运行sum()
而不阻塞主线程,
CoroutineScope(Dispatchers.IO).launch {
measureTimeMillis {
Log.d("TAG", "sum=${sum().await()}")
}.also {
Log.d("TAG", "Completed in $it ms")
}
}