文章目录
- 前言
- 一、 协程是什么?
- 二、协程使用步骤
- 1.引入库
- 2.开始使用协程
- 3.集成viewMode使用:viewModelScope
- 4.async与launch
- 三、suspend挂起函数关键字
- 总结
前言
为了适应Android发展潮流和学习GitHub上大佬们的代码学习Kotlin协程使用
一、 协程是什么?
- 轻量:您可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
- 内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。
- 内置取消支持:取消操作会自动在运行中的整个协程层次结构内传播。
二、协程使用步骤
1.引入库
//协程核心库
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
2.开始使用协程
开启一个简单全局协程
GlobalScope.launch { //GlobalScope 启动新的协程,它的生命周期只受整个应用程序的生命周期限制
val banner = MM.getData().getBanner().execute().body()
Log.i(TAG, "${banner?.msg}")
}
MM.getData().getBanner()
这是我retrofit封装的一个请求
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
class MM {
companion object{
fun getData(): Api =
Retrofit.Builder().addConverterFactory(GsonConverterFactory.create()).baseUrl("http://124.93.196.45:10002")
.build().create(Api::class.java)
}
}
Api.kt
interface Api {
@GET("/userinfo/xx")
fun getBanner():Call<Carousel>
}
开始切换线程
GlobalScope.launch(Dispatchers.Main) {
val banner = withContext(Dispatchers.IO) { MM.getData().getBanner().execute().body() } //数据请求
textView72.text = banner.msg //更新ui
}
简化封装使用
GlobalScope.launch { //Lambada
val banner = MM.getData().getBanner_kt() //封装成挂起函数
textView72.text = banner.msg //更新ui
}
多协程异步处理
GlobalScope.launch{
val async = async { MM.getData().getBanner_kt() } //异步
val async2 = async { MM.getData().getBanner_kt() }
val b = async.await().msg + async2.await().msg
textView72.text = b.toString()
}
api.kt
//挂起函数
@GET("/userinfo/xx")
suspend fun getBanner_kt():Carousel //声明suspend函数
3.集成viewMode使用:viewModelScope
viewModelScope 是预定义的 CoroutineScope,包含在 ViewModel KTX 扩展中。请注意,所有协程都必须在一个作用域内运行
添加依赖
//集成viewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
这里新建一个Viewmodel类
class MyViewModel : ViewModel(){
fun loadData(){
viewModelScope.launch(Dispatchers.IO){
val banner = MM.getData().getBanner().execute().body() //retrofit同步请求
println(banner?.msg)
}
}
}
- launch 是一个函数,用于创建协程并将其函数主体的执行分派给相应的调度程序。
- Dispatchers.IO 指示此协程应在为 I/O 操作预留的线程上执行。
当然也可以使用Lmbada写法
viewModelScope.launch{
val banner = MM.getData().getBanner().execute().body() //retrofit同步请求
println(banner?.msg)
}
不过这里的默认模式是主线程的
在ViewModel里面使用的好处:
在 ViewModel 的作用域内执行。如果 ViewModel 因用户离开屏幕而被销毁,则 viewModelScope 会自动取消,且所有运行的协程也会被取消
最后控制台成功打印
I/System.out: 查询成功
4.async与launch
launch 更多是用来发起一个无需结果的耗时任务(如批量文件删除、创建),这个工作不需要返回结果。async 函数则是更进一步,用于异步执行耗时任务,并且需要返回值(如网络请求、数据库读写、文件读写),在执行完毕通过 await() 函数获取返回值。
网络异步处理
lifecycleScope.launch{ //异步处理
try {
val bannerKt = MM.getData().getBanner_kt()
textView72.text = bannerKt.msg
} catch (e: Throwable) {
}
}
三、suspend挂起函数关键字
协程概念:启动一个协程可以使用 launch 或者 async 函数,协程其实就是这两个函数中闭包的代码块。
挂起函数:协程的代码块中,线程执行到了 suspend 函数这里的时候,就暂时不再执行剩余的协程代码,跳出协程的代码块,继续走主线程。
首先自定义一个挂起函数
//挂起函数 当有耗时操作,自定义延迟操作时,
private suspend fun loadData2()= withContext(Dispatchers.IO){ MM.getData().getBanner().execute().body() }
在主线程中调用:可以看到报错
那么挂起函数只能写在被另一个挂起函数里或协程里
在声明suspend关键字的函数里要有其他挂起函数的调用不然和普通方法没有区别
其中withContext()就是一个挂起函数它的作用是对线程进行切换
常用的 Dispatchers ,有以下三种:
- Dispatchers.Main:Android 中的主线程
- Dispatchers.IO:针对磁盘和网络 IO 进行了优化,适合 IO 密集型的任务,比如:读写文件,操作数据库以及网络请求
- Dispatchers.Default:适合 CPU 密集型的任务,比如计算
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。