一.概念
1.非阻塞挂起
协程中执行的任务,从协程所运行的线程剥离,所在的线程继续执行自己的任务。这个剥离也就叫做挂起。挂起通过挂起函数实现。因为挂起之后,所在的线程继续执行自己的任务,不会受到任何影响,所以称为非阻塞挂起。
2.suspend
suspend用来修饰函数,作用是提醒这是一个挂起函数,协程运行到该函数的时候,会挂起。当然suspend不是实现挂起的作用。只是用来提醒,真正实现挂起的是suspend修饰的函数中的代码。suspend函数因为是用来提醒挂起协程的,所以suspend修饰的函数只能运行在协程体内,或者运行在suspend修饰的函数内。
二.例子
package com.example.kotlin01
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tv_test.setOnClickListener {
//1.指定协程再主线程中执行
GlobalScope.launch(Dispatchers.Main) {
Log.e("1 MainActivity", "当前线程: ${Thread.currentThread().name}")
//2.调用suspendingGetImage函数
val result = suspendingGetImage("你好")
//5.suspendingGetImage函数执行完毕之后,自动切换到原来的线程,主线程,设置UI
Log.e("2 MainActivity", "当前线程: ${Thread.currentThread().name}")
tv_test.setText(result)
}
}
}
/**
* 3.suspendingGetImage函数使用suspend关键字修饰,提醒当前是一个挂起函数,
* 使用withContext挂起函数,将协程挂起,挂起的原理就是从原来的主线程剥离,挂起之后,原来的主线程继续执行自己的任务,不会有任何影响
* 4.使用Dispatchers调度线程,将协程切换到IO线程中运行
*
*/
suspend fun suspendingGetImage(id: String): String = withContext(Dispatchers.IO) {
Log.e("3 MainActivity", "当前线程: ${Thread.currentThread().name}")
id
}
}
image.png
以上的代码点击事件中执行了以下的过程:
- 1.指定协程再主线程中执行
- 2.调用suspendingGetImage函数
- 3.suspendingGetImage函数使用suspend关键字修饰,提醒当前是一个挂起函数, 使用withContext挂起函数,将协程挂起,挂起的原理就是从原来的主线程剥离,挂起之后,原来的主线程继续执行自己的任务,不会有任何影响
- 4.使用Dispatchers调度线程,将协程切换到IO线程中运行
- 5.suspendingGetImage函数执行完毕之后,自动切换到原来的线程,主线程,设置UI
网友评论