implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1"
// 此依赖库是 Android 项目才会用到的,纯 Kotlin 程序其实用不到。
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"
fun main(){
GlobalScope.launch {
println("codes run in coroutine scope")
//日志无法打印,因为代码块中的代码还没来得及运行,应用程序就结束了
}
}
可以创建一个协程的作用域,函数的代码块就是在协程中运行的。
GlobalScope.launch函数每次创建的都是一个顶层协程,这种协程当应用程序结束时也会跟着一起结束
fun main(){
GlobalScope.launch {
println("codes run in coroutine scope")
delay(1500)
println("code run in coroutine scope finished")
//不会被打印出来,没有来得及
}
Thread.sleep(1000)
}
让当前协程延迟指定时间后再运行;非阻塞式的挂起函数,只会挂起当前协程,不影响其他协程的运行;只能在协程的作用域或其他挂起函数中调用
会阻塞当前线程,运行在该线程下的所有协程都会被阻塞
runBlocking {
println("codes run in coroutine scope")
delay(1500)
println("code run in coroutine scope finished")
}
会创建一个协程的作用域,保证在协程作用域内的所有代码和子协程没有全部执行完之前一直阻塞当前线程(一般在测试环境下使用)
使用launch函数
fun main(){
runBlocking {
launch {
println("launch1")
delay(1000)
println("launch1 finished")
}
launch {
println("launch2")
delay(1000)
println("launch1 finished")
}
}
}
//结果:
launch1
launch2
launch1 finished
launch1 finished
//像多线程那样并发运行,实际这两个子协程运行在同一个线程中
只是由编程语言决定如何在多个协程之间进行调度,不需要操作系统参与,使协程的并发效率很高
suspend fun printDot(){
println(".")
delay(1000)
}
suspend fun printDot() = coroutineScope{
launch {
println(".")
delay(1000)
}
}
GlobalScope.launch:任意地方都可调用
runBlocking:任意地方调用
coroutineScope:协程作用域或挂起函数中调用
lanuch:在协程作用域中调用
GlobalScope.launch函数和lanuch函数都会返回一个Job对象,调用Job对象的cancel()方法
val job = GlobalScope.launch {
//具体逻辑
}
job.cancel()
实际项目中比较常用的写法:
val job = Job()
val scope = CoroutineScope(job)
//CoroutineScope()是个函数
//有了CoroutineScope对象之后就可以随时调用它的launch函数创建一个协程
scope.launch {
//处理具体逻辑
}
job.cancel()
runBlocking {
val result = async {
5+5
}.await()
println(result)
}
例子:
//1.首先定义一个request()函数
suspend fun request(address:String):String{
//挂起函数,接受一个address参数
//调用suspendCoroutine函数,当前协程会被立刻挂起,Lambda表达式中的代码会在普通线程中执行
return suspendCoroutine { continuation ->
HttpUtil.sendHttpRequest(address,object : HttpCallbackListener{
//HttpUtil.sendHttpRequest()方法发起网络请求,通过传统回调方式监听请求结果
override fun onFinish(response:String){
continuation.resume(response)
//请求成功,Continuation的ewsume()方法恢复被挂起的协程
//并传入服务器响应的数据,该值会成为suspendCoroutine函数的返回值
}
override fun onError(e:Exception){
continuation.resumeWithException(e)
//请求失败,调用continuation.resumeWithException()恢复被挂起的协程
//并传入具体的异常原因
}
})
}
}
//2.使用
suspend fun getBaiduResponse(){
try {
val response = request("https://www.baidu.com/")
//对服务器响应的数据进行处理
}catch (e:Exception){
//对异常情况进行处理
}
}
使用Retrofit发起网络请求
val appService = ServiceCreator.create<AppService>()
appService.getAppData().enqueue(object : Callback<List<App>>{
override fun onResponse(call:Call<List<App>>,response:Response<List<App>>){
//得到服务器返回的数据
}
override fun onFailure(call:Call<List<App>>,t:Throwable){
//对异常情况进行处理
}
})
使用suspendCoroutine函数进行简化
//不同的Service接口返回的数据类型不同,使用泛型的方式,定义一个await()函数
//await()函数是一个挂起函数,声明了一个泛型T,将await函数定义成了Call的扩展函数
//所有返回值是Call类型的Retrofit网络请求接口都可以直接调用await()函数
suspend fun <T> Call<T>.await():T{
//使用suspendCoroutine函数挂起当前协程
//现在拥有了Call对象的上下文,直接调用enqueue()方法让Retrofit发起网络请求
return suspendCoroutine { continuation ->
enqueue(object :Callback<T>{
override fun onResponse(call: Call<T>?, response: Response<T>?) {
val body = response.body()
if(body!=null) continuation.resume(body)
else continuation.resumeWithException(
RuntimeException("response body is nulll"))
}
override fun onFailure(call: Call<T>?, t: Throwable?) {
continuation.resumeWithException(t)
}
})
}
}
//使用
suspend fun getAppData(){
try{
val appList = ServiceCreator.create<AppService>().getAppData().await()
//得到服务器返回的数据
}catch(e:Exception){
//对异常情况进行处理66
}
}
通过DSL可以编写出一些看似脱离其原始语法结构结构的代码,从而构建出一种专有的语法结构
添加依赖库
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
class Dependency{
val libraries = ArrayList<String>()
//List集合保存所有的依赖库
fun implementation(lib:String){
//提供一个implementation()方法用于向List集合中添加依赖库
libraries.add(lib)
}
}
fun dependencies(block:Dependency.() -> Unit):List<String>{
val dependency = Dependency()
dependency.block()
return dependency.libraries
}
dependencies {
implementation ("com.squareup.retrofit2:retrofit:2.6.1")
implementation ("com.squareup.retrofit2:converter-gson:2.6.1")
}
//dependencies函数接收一个函数类型参数,这里传入一个Lambda表达式
//此时Lambda表达式拥有Dependency类的上下文,可以直接调用Dependency类中的implementation()方法