当前位置: 首页 > news >正文

Kotlin 协程与挂起函数(Coroutines suspend)入门到实战

Kotlin 协程与挂起函数(Coroutines & suspend)入门到实战

Kotlin 协程是 Android 和后端 Kotlin 开发里最核心的异步方案之一。

很多人第一次学协程时会卡在几个地方:

  • suspend到底是什么?
  • 协程是不是线程?
  • 为什么不会阻塞?
  • launchasyncwithContext有什么区别?
  • Android 项目到底该怎么用?

这篇教程按**“从能看懂 → 能写 → 能实战”**的方式讲。


一、为什么需要协程?

先看传统代码:

fundownloadData(){Thread{Thread.sleep(3000)runOnUiThread{textView.text="下载完成"}}.start()}

问题:

  • 回调嵌套
  • 线程管理麻烦
  • 容易内存泄漏
  • 异步代码像"地狱"

协程的写法:

lifecycleScope.launch{delay(3000)textView.text="下载完成"}

是不是像同步代码?但它实际上是异步的

这就是协程最大的意义:

用同步代码的写法,完成异步操作。


二、什么是协程(Coroutine)

协程可以理解为:“轻量级线程”

但它不是线程

线程 vs 协程

对比线程协程
系统级
创建成本极低
切换成本很低
数量可以很多
阻塞容易默认非阻塞
依赖关系线程包含协程协程运行在线程上

比如:

repeat(100000){launch{delay(1000)}}

10万个协程都没问题。但10万个线程直接炸。


三、挂起函数 suspend 到底是什么?

这是最关键的地方。

1. suspend 不是异步

很多人误解:

suspendfuntest()

自动开线程
自动异步

suspend的真正含义:

这个函数可以"暂停"而不阻塞线程。

2. 什么叫"挂起"?

suspendfunloadData(){delay(3000)println("完成")}

这里delay(3000)会:

  • 暂停当前协程
  • 释放线程
  • 3秒后恢复

注意:线程没有被卡死。

3. Thread.sleep 和 delay 的区别

// Thread.sleepThread.sleep(3000)// 特点:阻塞线程,什么都干不了// delaydelay(3000)// 特点:只暂停协程,不阻塞线程

直观理解

假设:

  • 线程 = 厨房
  • 协程 = 厨师
Thread.sleepdelay
厨师睡觉厨师说:“3秒后叫我”
厨房也废了厨房还能给别人做饭

这就是协程高性能的核心。


四、协程的基本使用

先添加依赖:

implementation"org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"

五、launch:启动协程

GlobalScope.launch{delay(1000)println("协程执行")}
launch 特点说明
启动协程无返回值
异步执行类似new Thread(),但更轻量

六、runBlocking(学习阶段使用)

funmain()=runBlocking{launch{delay(1000)println("协程")}println("开始")}

输出:

开始 协程

runBlocking是什么?

  • 作用:阻塞当前线程,直到内部协程结束
  • 适合:学习、测试
  • 不适合:Android 主线程

七、async 与 await

需要返回值时:

runBlocking{valresult=async{delay(2000)"请求成功"}println(result.await())}
async 特点说明
有返回值返回Deferred
await()等待结果

八、协程调度器 Dispatcher

协程运行在哪个线程?由Dispatcher决定。


九、常见 Dispatcher

1. Main

  • 主线程
  • Dispatchers.Main
  • 用于:更新UI

2. IO

  • IO线程池
  • Dispatchers.IO
  • 用于:网络、数据库、文件

3. Default

  • CPU密集型
  • Dispatchers.Default
  • 用于:排序、JSON解析、大计算

十、withContext:线程切换

最常用。

lifecycleScope.launch{valresult=withContext(Dispatchers.IO){// 网络请求"服务器数据"}textView.text=result}

执行流程:

主线程:launch ↓ 切换IO线程:withContext(IO) ↓ 执行完成 ↓ 自动回主线程

十一、协程作用域 CoroutineScope

协程必须运行在作用域里。


十二、GlobalScope 为什么不推荐?

GlobalScope.launch{}

问题:

  • 生命周期不可控
  • 容易内存泄漏
  • Activity销毁还在运行

所以:Android开发基本不用。


十三、Android 正确写法

lifecycleScope

// ActivitylifecycleScope.launch{}// FragmentviewLifecycleOwner.lifecycleScope.launch{}

特点:页面销毁自动取消协程


十四、ViewModel 中使用

classMainViewModel:ViewModel(){funload(){viewModelScope.launch{valdata=withContext(Dispatchers.IO){api.getData()}}}}

这是Android 官方推荐方案


十五、协程取消机制

valjob=launch{repeat(100){delay(1000)println(it)}}job.cancel()

为什么协程能取消?因为delay()会检查取消状态。


十六、Job

每个协程都有 Job。

valjob=launch{}

作用:canceljoin、管理生命周期


十七、join()

等待协程结束:

valjob=launch{delay(2000)}job.join()println("结束")

十八、异常处理

try-catch

launch{try{valdata=api.load()}catch(e:Exception){// 处理异常}}

十九、SupervisorJob

普通情况下:一个子协程崩了,全部取消。

SupervisorJob:

valscope=CoroutineScope(SupervisorJob()+Dispatchers.Main)

特点:一个失败,不影响其他协程。Android 很常用。


二十、协程常见面试题

1. suspend 和 coroutineScope 区别?

  • suspend— 只是说明函数可挂起
  • coroutineScope— 会创建协程作用域

2. launch 和 async 区别?

launchasync
无返回值有返回值
返回 Job返回 Deferred

3. delay 为什么不卡线程?

因为:

  • 它会挂起协程
  • 不阻塞线程

4. 协程是不是线程?

不是。协程运行在线程上。


二十一、Android 实战案例

场景1:网络请求

viewModelScope.launch{try{valdata=withContext(Dispatchers.IO){api.getUser()}tvName.text=data.name}catch(e:Exception){toast("请求失败")}}

场景2:并发请求

viewModelScope.launch{valuserTask=async(Dispatchers.IO){api.getUser()}valvideoTask=async(Dispatchers.IO){api.getVideo()}valuser=userTask.await()valvideo=videoTask.await()}

优势:两个请求同时执行。

场景3:倒计时

lifecycleScope.launch{for(iin10downTo0){tv.text="$i"delay(1000)}}

二十二、Flow 与协程关系

很多人混淆。

协程Flow
解决:一个异步任务解决:连续的数据流

比如:搜索输入、股票数据、聊天消息、Room数据库监听

简单例子:

flow{emit(1)delay(1000)emit(2)}

二十三、协程学习路线(推荐)

建议顺序:

  1. launch
  2. suspend
  3. delay
  4. async/await
  5. Dispatcher
  6. withContext
  7. lifecycleScope
  8. viewModelScope
  9. Job
  10. Flow

二十四、协程核心理解(最重要)

suspend = 可以暂停协程,但不会阻塞线程

你就已经超过很多只会背API的人了。


二十五、实际开发最佳实践

1. 不要用 GlobalScope

改用:

  • viewModelScope
  • lifecycleScope

2. IO任务放 Dispatchers.IO

withContext(Dispatchers.IO)

3. UI更新必须 Main线程

Dispatchers.Main

4. Repository 不要持有 Scope

错误:

classRepository{valscope=CoroutineScope(...)}

容易泄漏。


二十六、完整 Android MVVM 示例

ViewModel

classUserViewModel:ViewModel(){valuserLiveData=MutableLiveData<User>()funloadUser(){viewModelScope.launch{valuser=withContext(Dispatchers.IO){api.getUser()}userLiveData.value=user}}}

Activity

viewModel.userLiveData.observe(this){tvName.text=it.name}

二十七、总结

核心作用
suspend挂起函数
launch启动协程
async异步返回值
delay非阻塞等待
withContext切线程
Dispatcher指定线程
viewModelScopeAndroid推荐作用域
Flow数据流

最后一段(真正理解协程)

很多人学协程,只会背:

  • launch
  • async
  • withContext

但真正重要的是:

协程的本质不是"开线程"。

而是:用极低成本管理大量异步任务。

http://www.jsqmd.com/news/818858/

相关文章:

  • 1.5A,30VIN,XZ4120,降压恒流LED驱动芯片 SOT89-5,ESOP8
  • rpc和http的区别
  • 【开源】电商运营场景的 Agent :EcomPilot经营诊断神器 附github
  • Android Studio的安装及配置 创建项目编译、运行、调试、打包安装包
  • Parsec VDD虚拟显示器终极实战指南:从零构建高性能游戏串流环境
  • innovus : assignPGBumps assignsignalbump
  • 保姆级教程:用Python手写牛顿迭代法求平方根(附完整代码与可视化)
  • OBS Advanced Timer:6种专业计时模式让直播时间管理更精准
  • 基于LLM的BI工具AI助手:自然语言查询与数据分析实践
  • 2026年液压坝技术全解析:溢流闸、船闸、节制闸、蓄水坝、钢坝、钢闸门、防洪闸、合页坝、底轴旋转坝、弧形闸门、拦河坝选择指南 - 优质品牌商家
  • 大数据“杀熟”将被严查:技术人如何用中间件构建合规的数据治理体系?
  • 如何在项目中引入googtest(上)——通过编译器引入库
  • 量子变分算法中的参数偏移规则与梯度估计优化
  • 2026年5月西安老房改造避坑指南:为何业之峰装饰集团未央分公司是可靠之选? - 2026年企业推荐榜
  • 本专栏配套项目概览:一个可对话、可搜索、可生成报告的智能助手
  • Excel中以当前列的数值作为查找条件,查找匹配的行
  • 如何用Python快速接入Taotoken调用多模型API完成项目开发
  • 衍射光栅散射光与杂散光:产生根源、量化评估与全链路抑制策略
  • 3个专业音频处理方案:MPC-HC的zita-resampler集成与音频渲染优化教程
  • CircuitPython嵌入式开发入门:从LED闪烁到DVI显示的综合实践指南
  • 2026水循环制冷机电话推荐榜:河南制冷、河南制冷设备、济南制冷、浙江冷水机、深圳冷水机、潍坊冷水机、潍坊制冷选择指南 - 优质品牌商家
  • 自动化运维工具 Ansible 概述及命令行模块怎么用?
  • 工业 DC-DC 选型性能适配解析:钡特电源 VB10-48D15MD 与 URA4815YMD-10WR3 封装互通
  • SkillHarness:轻量级技能编排框架,构建可维护的AI与自动化工作流
  • ESP32协处理器实战:Adafruit AirLift为微控制器提供稳定WiFi/BLE连接
  • Windows风扇控制软件FanControl:专业级散热管理解决方案
  • ESP32物联网网关开发实战:从硬件选型到实时控制协议设计
  • 企业级矩阵系统分布式素材处理与多平台自适应转码技术实践
  • 如何快速获取9大网盘真实下载地址:LinkSwift网盘直链下载助手完整指南
  • 前端鼠标跟随器实现:从原理到实战性能优化