📜  Kotlin协程中的挂起函数

📅  最后修改于: 2021-05-10 14:41:19             🧑  作者: Mango

先决条件: Android上的Kotlin协程

Kotlin团队将协程定义为“轻量级线程”。它们是实际线程可以执行的任务。协程是在1.3版中添加到Kotlin的,它基于其他语言的既定概念。 Kotlin协程引入了一种新的并发样式,可以在Android上使用它来简化异步代码。

Kotlin中的挂起函数

暂停函数是可以启动,暂停和恢复函数。关于挂起函数要记住的最重要的一点是,仅允许从协程或另一个挂起函数。下面给出一个示例,其中我们尝试从协程外部调用delay()函数。

Kotlin
// sample kotlin program to show use of delay function
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
        // will throw a error
        delay(1000L)
          
        GlobalScope.launch{
         // delay function (a suspend function) must called within coroutine
         // or another suspend function
        } 
    }
}


Kotlin
// arbitrary do task function for explanation
suspend fun dotask(request: Request): Response
{
  // perform the task
}


Kotlin
// internal conversion of suspend function dotask()
fun dotask(request: Request, continuation: Continuation)...


Kotlin
// Continuation interface structure
public interface Continuation
{
  public val context: CoroutineContext
  public fun resumeWith(result: Result)
}


Kotlin
// Kotlin Program to demonstrate use of suspend function
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
          GlobalScope.launch{
          val networkCallAnswer==doNetworkCall()
          Log.d("Main-Activity,networkCallAnswer)
        } 
    }
      
    suspend fun doNetworkCall():String {
    delay(2000L);
    return "Network Call Answer"
    }               
}


正如我们从协程外部调用延迟函数,它将引发如下错误:

将鼠标悬停在延迟函数上,我们可以看到错误。

延迟函数

它表示为delay() 它是一个暂停函数,它将协程延迟给定时间而不阻塞线程,并在指定时间后恢复它。当我们在函数添加suspend关键字时,所有合作都会自动为我们完成。我们不必使用“何时”或“切换大小写”来从一个功能切换到另一个函数。让我们以一个suspend函数为例:

科特林

// arbitrary do task function for explanation
suspend fun dotask(request: Request): Response
{
  // perform the task
}

尽管似乎只有一个参数传递给dotask()函数,但内部有两个参数。在内部,它由编译器转换为另一个函数,而无需使用带有Continuation 类型的额外参数的suspend关键字,如下所示:

科特林

// internal conversion of suspend function dotask()
fun dotask(request: Request, continuation: Continuation)...

挂起函数相互通信的方式是使用Continuation对象。 Continuation只是具有一些额外信息的通用回调接口,如下所示(取自Kotlin源代码):

科特林

// Continuation interface structure
public interface Continuation
{
  public val context: CoroutineContext
  public fun resumeWith(result: Result)
}
  • context将是在该延续中使用的CoroutineContext。
  • resumeWith使用Result恢复协程的执行,该结果可以包含一个值,该值是导致挂起的计算结果或异常。

resumeWith的两个扩展功能由以下给出:

我们可以看到两个扩展函数,它们可以用于以返回值或异常(如果在函数挂起时发生错误)来恢复协程。这样,可以在Continuation的帮助下启动,暂停和恢复函数。我们只需要使用suspend关键字即可。

科特林

// Kotlin Program to demonstrate use of suspend function
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
          
          GlobalScope.launch{
          val networkCallAnswer==doNetworkCall()
          Log.d("Main-Activity,networkCallAnswer)
        } 
    }
      
    suspend fun doNetworkCall():String {
    delay(2000L);
    return "Network Call Answer"
    }               
}

延迟2秒后,我们获得了Log输出,因为我们已经从协程调用了doNetworkCall() ,所以必须将doNetworkCall()函数为suspend。

想要一个节奏更快,更具竞争性的环境来学习Android的基础知识吗?
单击此处,前往由我们的专家精心策划的指南,以使您立即做好行业准备!