Kotlin协程使用


前言

为了适应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提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值