先决条件: Android上的Kotlin协程
Kotlin团队将协程定义为“轻量级线程”。它们是实际线程可以执行的任务。协程是在1.3版中添加到Kotlin的,它基于其他语言的既定概念。 Kotlin协程引入了一种新的并发样式,可以在Android上使用它来简化异步代码。
The official documentation says that coroutines are lightweight threads. By lightweight, it means that creating coroutines doesn’t allocate new threads. Instead, they use predefined thread pools and smart scheduling for the purpose of which task to execute next and which tasks later.
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
科特林
// 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恢复协程的执行,该结果可以包含一个值,该值是导致挂起的计算结果或异常。
Note: From Kotlin 1.3 onwards, you can also use the extension functions resume(value: T) and resumeWithException(exception: Throwable) which are specialized versions of the resumeWith call.
resumeWith的两个扩展功能由以下给出:
- fun
Continuation .resume(value: T) - fun
Continuation .resumeWithException(exception: Throwable)
我们可以看到两个扩展函数,它们可以用于以返回值或异常(如果在函数挂起时发生错误)来恢复协程。这样,可以在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。