Kotlin 科特林合作项目。API调用完成时运行代码

Kotlin 科特林合作项目。API调用完成时运行代码,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,我对协同程序有一个顾虑。我想做的是在几个请求完成后执行一个特定的代码。。。在我使用completionHandlers并正确工作之前,问题是有更多的请求,我不想嵌套它们,我认为这不是正确的做法。。。所以我不知道你对这个练习有什么建议。我提出以下建议,但我不确定这是否是最好的: val job = viewLifecycleOwner.lifecycleScope.launch { // API calls Process1 (view)

我对
协同程序有一个顾虑。我想做的是在几个请求完成后执行一个特定的代码。。。在我使用
completionHandlers
并正确工作之前,问题是有更多的请求,我不想嵌套它们,我认为这不是正确的做法。。。所以我不知道你对这个练习有什么建议。我提出以下建议,但我不确定这是否是最好的:

  val job = viewLifecycleOwner.lifecycleScope.launch {
             // API calls
             Process1 (view)
             Process2 (view)
             Process3 (view)
             Process4 (view)
         }
         runBlocking {
             job.join ()
             // Continue normally
         }
谢谢你的阅读


每个“进程”调用一个
API
,并作为一个
completionHandler
响应。下面是一个简单的示例,说明了从协程返回值的两种不同方法。 您不能保证协程何时返回或完成,因此您必须拥有某种回调函数,该函数可以处理api返回数据,或者可以使用withContext方法更接近正常的代码流。无论采用哪种方式,协同程序代码都不能与同步代码连接起来,并且运行阻塞被认为是不好的做法

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MyViews {
    private val apis = Apis()
    
    fun onViewCreate() {
        // Using example of launch -- cannot return value
        // This code will split off from the sync flow, and we cannot guarantee when any of it is ran, except the order it will be run in
        CoroutineScope(Dispatchers.IO).launch {
            // One method to elevate values out of a coroutine would be callbacks
                callApisWithCallbacks { data -> 
                    processApiData(data)
                }
        }
        
        // Internally this utilizes withContext to resolve a value that is ready to be used 
        callApisWithReturn()
        
        // Continue normal work flow here
    }
    
    fun processApiData(age: Int) {
        // Do work here
        println("Current users age: $age")
    }

    fun callApisWithReturn() {
        // Use launch to get into coroutine from sync code
        CoroutineScope(Dispatchers.Default).launch {
            // withContext will return a value and can be used as if inline
            val userAge = withContext(Dispatchers.IO) { apis.getUserAge() }
            processApiData(userAge)
        } 
        
        // Suspend function cant be called outside of coroutine
        // apis.getUserAge()
    }

    suspend fun callApisWithCallbacks(cb: (Int) -> Unit) {
        val age = apis.getUserAge()
        cb(age)
    }
}

class Apis {

    suspend fun getUserAge(): Int {
        // Simulate delay from API
        delay(1000)

        return 5
    }
}

将进程函数转换为挂起函数。他们应该在后台线程上执行阻塞工作。然后,在调用它们之后,您可以在协同程序内正常继续。要在后台线程上执行此工作,可以将阻塞工作包装在
withContext(Dispatchers.IO)
中。如果您使用的API使用回调参数,可以使用
suspendCoroutine
将其转换为挂起函数。请给我举个例子好吗?这篇由coroutines设计负责人撰写的文章清楚地描述了挂起函数以及如何使用
与上下文
。非常有用!!很多