【问题标题】:Kotlin coroutines. Run code when API calls finishKotlin 协程。 API 调用完成时运行代码
【发布时间】:2021-03-19 18:51:10
【问题描述】:

我担心coroutines。我想做的是在完成几个请求后执行特定代码......在我使用completionHandlers并正常工作之前,问题是有更多请求,我不想嵌套它们,我认为这不是正确的做法......所以我不知道你是否对这个练习有任何建议。我提出以下建议,但我不确定它是否是最好的:

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

感谢阅读!

附言。每个“进程”调用API 并以completionHandler 响应

【问题讨论】:

  • 将您的流程函数转换为挂起函数。他们应该在后台线程上进行阻塞工作。然后您可以在调用它们后立即在协程内正常继续。要在后台线程上完成工作,您可以将阻塞工作包装在 withContext(Dispatchers.IO) 中。如果您正在使用带有回调参数的 API,则可以使用 suspendCoroutine 将其转换为挂起函数。
  • 你能给我举个例子吗?
  • 协程设计负责人的这篇文章清楚地描述了挂起函数以及如何使用withContextelizarov.medium.com/…
  • 非常有用!!非常感谢

标签: kotlin kotlin-coroutines


【解决方案1】:

这是一个简单的例子,展示了从协程返回值的 2 种不同方法。 您无法保证协程何时返回或完成,因此您必须有某种回调函数来处理您的 api 返回数据,或者您可以使用 withContext 方法来更接近正常的代码流来处理它。无论哪种方式,协程代码都无法与同步代码连接,runBlocking 被认为是不好的做法。

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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    相关资源
    最近更新 更多