kotlin协程小结

本文介绍了Kotlin协程的基本概念,强调其轻量级、内存泄漏少和内置取消支持的特点。通过示例展示了如何在Android环境中使用协程,包括GlobalScope的协程构造函数如launch和async,以及suspend、withContext等关键函数的运用。同时,讨论了Kotlin提供的Dispatchers调度器,如Dispatchers.IO和Dispatchers.Main,用于在不同线程间切换。协程的Job管理则允许我们对协程进行取消操作,以控制其生命周期。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

协程是什么:

  • 协程是Kotlin中有特色的一项技术,大部分编程语言没有协程这个概念。协程可简单理解成轻量级的线程。线程是由系统调度的,线程切换或线程阻塞的开销都比较大。而协程依赖于线程,但是协程挂起时不需要阻塞线程,几乎是无代价的。一个线程内可创建多个协程,协程可在编程语言层面实现不同协程之间的切换,从而在单线程模式下模拟多线程的效果。其中的原理是协程可在某个地方挂起,并且可以重新在挂起处继续运行。而代码执行时的挂起与恢复完全由编程语言控制,与操作系统无关。

协程特点:

轻量

可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作

内存泄漏更少

用的结构化并发机制能帮助追踪运行在协程中的任务,比如在不需要协程的时候取消任务,协程运行时追踪任务,协程执行失败时传播错误信号

内置取消支持

取消操作会自动在运行中的整个协程层次结构内传播

jetpack集成

许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可用于结构化并发。


协程使用:

提示:Kotlin没有将协程纳入标准库的API中,而是以依赖库的形式提供。 使用前需在app/build.gradle文件中添加如下依赖库

例如:

	implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
	//用于android
	implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1"	

代码实例

class LoginViewModel(
    private val loginRepository: LoginRepository
): ViewModel() {

    fun login(username: String, token: String) {
        //新建一个协程,从UI线程移出
        viewModelScope.launch(Dispatchers.IO) {
            val jsonBody = "{ username: \"$username\", token: \"$token\"}"
            loginRepository.makeLoginRequest(jsonBody)
        }
    }
}

代码分析

viewModelScope :是在ViewModel KTX扩展中已定义的CoroutineScope(协程作用域),所有的协程都必须在一个作用域内运行。

常见的创建协程作用域方法如下:

fun abc(){
    val scope = CoroutineScope(Dispatchers.Main)
        scope.launch { 
        //填入代码
        }
}

或者将类继承自CoroutineScope,整个类内即协程作用域

class abc() :CoroutineScope{
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main

    fun abcd(){
        launch { 
            //填入代码
        }
    }
}

kotlin 中 GlobalScope 类提供了几个创建协程的构造函数:

协程构造器

launch: 创建协程
async : 创建带返回值的协程,返回的是 Deferred 类; 可使用 await 的挂起函数调用
withContext:不创建新的协程,指定协程上运行代码块
runBlocking:不是 GlobalScope 的 API,可以独立使用,区别是 runBlocking 里面的 delay 会阻塞线程,而 launch 创建的不会

suspend 挂起

其中suspend将函数声明为挂起函数,表示耗时操作。被suspend声明的函数只能在suspend函数或协程作用域内调用。

suspend fun abc(){
    val a = aysnc{
//填入代码
	return xxx;
}
var b = a.await()//调用
}

withContext 切换线程

withContext这个函数主要可以切换到指定的线程,并在闭包内的逻辑执行结束之后,自动把线程切回去继续执行:

//在viewmodel中
   suspend fun getCollectionResults(){
        withContext(Dispatchers.IO){
            /*val list= mutableListOf<CardInfo>()
            val info0=CardInfo("cctv1", "animals")
            val info1=CardInfo("cctv2", "economical")
            val info2=CardInfo("cctv13", "news")
            val info3=CardInfo("cctv6", "movie")
            list.apply { add(info0)
            add(info1)
            add(info2)
            add(info3)}
            for (i in 1..15){
                list.add( CardInfo("CCTV$i", "details_$i"))
            }
            delay(2000)*/
            val data= async { repository.getAllFavor() }

            val list=data.await()
            _collectionResults.postValue(list)
        }
    }

代码中将协程执行操作移置了I/O线程,避免在主线程做耗时操作,因此是主线程安全的

coroutineScope.launch(Dispatchers.Main) {      //  在 UI 线程开始
    val image = withContext(Dispatchers.IO) {  // 切换到 IO 线程,并在执行完成后切回 UI 线程
        getImage(imageId)                      // 将会运行在 IO 线程
    }
    avatarIv.setImageBitmap(image)             // 回到 UI 线程更新 UI
} 

Kotlin提供的调度程序

●Dispatchers.Main - 使用此调度程序可在 Android 主线程上运行协程。此调度程序只能用于与界面交互和执行快速工作。示例包括调用 suspend 函数,运行 Android 界面框架操作,以及更新 LiveData 对象。

● Dispatchers.IO - 此调度程序经过了专门优化,适合在主线程之外执行磁盘或网络 I/O。示例包括使用 Room 组件、从文件中读取数据或向文件中写入数据,以及运行任何网络操作。

● Dispatchers.Default - 此调度程序经过了专门优化,适合在主线程之外执行占用大量 CPU 资源的工作。用例示例包括对列表排序和解析 JSON。

● Dispatchers.Unconfined 不限制任何制定线程 高级调度器,不应该在常规代码里使用


可取消的Job:

使用 launch 或 async 创建的每个协程都会返回一个 Job 实例,该实例是其协程的唯一标识并管理其生命周期。 可以将 Job 传递给 CoroutineScope 以进一步管理其生命周期。

class ExampleClass {
    ...
    fun exampleMethod() {
        val job = scope.launch {
            // 新携程
        }

        if (...) {
            //job的取消并不影响scope
            job.cancel()
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值