Android Kotlin中协程详解
博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
👉点击跳转到教程
前言
Kotlin协程介绍:
Kotlin 协程是 Kotlin 语言中的一种用于处理异步编程的机制。它提供了一种轻量级的线程替代方案,允许你以更简洁和可读的方式编写并发代码。
使用Kotlin协程需要引入Kotlin协程依赖包,这里引入的Kotlin核心依赖包,需要根据当前项目使用的Kotlin版本来引入,我使用的Kotlin版本为1.4.32所以引入的Kotlin核心依赖包版本为:1.4.3
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
具体可以去到Maven Repository去查找使用对应的版本。
一、GloabalScope
1、使用GlobalScope构建协程。
GlobalScope.launch {Log.d("协程 当前线程:", Thread.currentThread().name)}
输出日志
2、launch中的代码段是执行在子线程中的,如果需要在开启协程的时候指定线程,
可以设置Dispatchers参数值。下面以开启协程并使其在I/O线程中执行为例。
GlobalScope.launch(Dispatchers.IO) {Log.d("Dispatchers.IO 当前线程:", Thread.currentThread().name)}
输出日志
3、取消协程 launch()返回一个Job对象,如果协程执行了一个耗时任务,如果耗时任务还未执行完,这是Activity被销毁,这是需要执行job.cancel(),来取消协程。终止后续代码的执行。
val job = GlobalScope.launch(Dispatchers.IO) {Log.d("Dispatchers.IO 当前线程:", Thread.currentThread().name)}//取消协程应该放在恰当的位置job.cancel()
二、CoroutineScope
1、通过CoroutineScope创建协程在实际项目中,用的较为广泛。
val job = Job()CoroutineScope(job).launch {//逻辑处理}job.cancel()
2、async,使用async来获取协程的执行结果。
详解async函数
aysnc函数同样可以构建一个协程作用域,并返回Deferred对象。但是与Coroutine-Scope函数不同的
是,async函数必须在协程作用域中才能调用
val job = Job()CoroutineScope(job).launch {//逻辑处理val result = async {//模拟耗时操作delay(3000)"操作成功"}.await()Log.d(TAG, result)}
输出日志,通过delay()函数,让协程延迟3秒执行。
实际使用过程中,可能会出现各种意外的情况,导致发生异常。这里举一个例子。
这里报的异常想必大家都知道 java.lang.ArithmeticException: divide by zero,不能除以0
但是我下面的做法并不能正确的捕获异常依然会报错,导致程序异常退出。
//错误写法val job = Job()CoroutineScope(job).launch {try {//逻辑处理val result = async {//模拟耗时操作delay(3000)"操作成功" + 6 / 0}.await()Log.d(TAG, result)} catch (e: Exception) {e.printStackTrace()}}
这是因为在协程作用域外层是无法捕获到协程异常的,这是因为已
经超出了协程作用域的范围,try catch必须包裹ascync函数开启的协程作用域。
val job = Job()CoroutineScope(job).launch {//逻辑处理val result = async {try {//模拟耗时操作delay(3000)"操作成功" + 6 / 0} catch (e: Exception) {"结果异常"}}.await()Log.d(TAG, result)}
3.await()方法,await()方法会阻塞当前协程(launch启动的外层协程),而不是 async 启动的内部协程,
/**启动 launch 协程。在 launch 协程中,首先启动第一个 async 协程,开始耗时操作。调用 await() 时,launch 协程会被暂停,直到第一个 async 协程完成。之后,继续执行外层 launch 协程,并启动第二个 async 协程。调用第二个 async 的 await(),再次暂停外层的 launch 协程,直到第二个 async 协程完成。一旦两个 async 协程都完成,launch 协程继续执行剩余逻辑。*/val job = Job()CoroutineScope(job).launch {val startTime = System.currentTimeMillis()//逻辑处理val result = async {//模拟耗时操作delay(3000)"操作成功"}.await()//逻辑处理val result2 = async {//模拟耗时操作delay(3000)"获取成功"}.await()Log.d(TAG, "执行结果:$result - $result2")val endTime = System.currentTimeMillis()Log.d(TAG, "执行时间: ${endTime - startTime}")}
输出结果
针对上述情况,我们可以在用到执行结果的时候调用wait()方法,这样就可以让result和result2同时执行了。
val job = Job()CoroutineScope(job).launch {val startTime = System.currentTimeMillis()//逻辑处理val result = async {//模拟耗时操作delay(3000)"操作成功"}//逻辑处理val result2 = async {//模拟耗时操作delay(3000)"获取成功"}Log.d(TAG, "执行结果:${result.await()} - ${result2.await()}")val endTime = System.currentTimeMillis()Log.d(TAG, "执行时间: ${endTime - startTime}")}
输出结果:
执行时间节省了3秒左右,因为程序同时调用了result和result2的await方法,这样result和result2相当于并行的关系,在实际项目中常有需要合并不同接口执行结果的需求,这时就 可以采用这种方式来提高运行效率。
三、withContext
1、通过withContext来构建协程作用域,withCotext是一个挂起函数。
首先来讲一下挂起函数。
在CoroutineScope(job).launch开启的协程中,通过会进行IO操作,或者网络请求的操作,为方便阅读通过会抽取到一个方法中,这里我声明了loadData()
val job = Job()CoroutineScope(job).launch {loadData()}fun loadData() {delay(2000)Log.d(TAG, "--loadData--")}
delay(2000)这个函数会报一个错误,Suspend function ‘delay’ should be called only from a coroutine or another suspend function。意思就是挂起函数delay()应该在协程作用域,或者另一个挂起函数中被调用。因此这里的loadData()函数,必须加上suspend。
那么这里可能就有人要问了,这个挂起函数有什么用呢,在实际项目中,我们可以封装一些网络请求,IO操作等耗时的功能封装在挂起函数,这样别人看到之后也能明白,这些挂起函数是要在协程中进行使用的。
所以suspend在Kotlin协程中起到的仅仅是提醒作用。
2、withCotext函数用法
val job = Job()CoroutineScope(job).launch {val result = withContext(Dispatchers.IO) {delay(2000)"获取成功"}Log.d(TAG, "$result")}
输出日志
withContext函数同样是一个挂起函数,需要在协程中或者另一个挂起函数中调用,withCotext函数会将最后一行执行结果作为返回值。
与async函数不同的是,withContext函数会强制要求传入一个线程参数,参数值类型有
Dispatchers.Default、Dispatchers.IO、Dispatchers.Main这三种,Dispatchers.Default常用于计算密集
型任务,Dispatchers.IO常用于网络请求、文件读写等操作,Dispatchers.Main则表示程序在主线程
中执行,所以当开启协程的时候,协程作用域中的代码不一定是执行在子线程的,这取决于这个线
程参数的值。
现在我们如何使用协程更优雅的操作UI呢
这里使用CoroutineScope开启Main协程,通过withContext开启I/O协程,当withContext协程作用域代码执行结束时,会继续回到Main协程执行UI的代码逻辑。示例代码如下:
val job = Job()CoroutineScope(job).launch(Dispatchers.Main) {val result = getResult()showUI(result)val result2 = getResult2()showUI(result2)}private suspend fun getResult(): String {return withContext(Dispatchers.IO) {delay(2000)"操作成功"}}private suspend fun getResult2(): String {return withContext(Dispatchers.IO) {delay(4000)"获取成功"}}private fun showUI(result: String) {Log.d(TAG, "showUI: ")tv_result.text = result}
输出日志:
从上述代码中可以看出,即使程序需要多次切换协程,也不需要像使用线程一样层层嵌套,这样就
实现了使用协程更优雅地实现异步任务。
相关文章:

Android Kotlin中协程详解
博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家, 👉点击跳转到教程 前言 Kotlin协程介绍: Kotlin 协程是 Kotlin 语言中的一种用于处理异步编程的机制。它提供了一…...
【webpack学习】
webpack由于历史包袱导致复杂,只要把握关键流程即可 webpack的主要流程loader plugin难点:HMR / 懒加载 原理webpack 的优化手段 构建工具对比 webpack :可以打包任何资源,配置略复杂,适合项目开发rollup࿱…...

H5实现PDF文件预览,使用pdf.js-dist进行加载
H5实现PDF文件预览,使用pdf.js-dist进行加载 一、应用场景 在H5平台上预览PDF文件是在原本已经开发完成的系统中新提出的需求,原来的系统业务部门是在PC端进行PDF的预览与展示,但是现在设备进行了切换,改成了安卓一体机进行文件…...
面试域——面试系统工程
摘要 1. 当前就业面试场景 1.1. 招聘市场的“551 定律” 你知道招聘市场的“551 定律”吗? 551 定律:每一层筛选环节都会有百分之十的折损率。一个岗位从接收简历到发下 Offer 至少要筛选 500 份左右的简历、面试 50 人左右、只有 5 人左右通过面试&am…...

PHP-FPM 性能配置优化
4 核 8 G 服务器大约可以开启 500 个 PHP-FPM,极限吞吐量在 580 qps (Query Per Second 每秒查询数)左右。 Nginx php-fpm 是怎么工作的? php-fpm 全称是 PHP FastCGI Process Manager 的简称,从名字可得知ÿ…...

渗透测试-百日筑基—SQL注入篇时间注入绕过HTTP数据编码绕过—下
day8-渗透测试sql注入篇&时间注入&绕过&HTTP数据编码绕过 一、时间注入 SQL注入时间注入(也称为延时注入)是SQL注入攻击的一种特殊形式,它属于盲注(Blind SQL Injection)的一种。在盲注中,攻击…...
Unity - UGUI动静分离
原理:UGUI 是基于Canvas来进行合并计算的 1.不同Cavans的UI元素,是无法合批渲染,无法实现同一个drawcall 2. 每次合批的时候,会合并计算Canvas下所有的UI元素 , 具体流程: Step1: 对Cavans下所有的UI元素进行合批计算 Step2: …...
arm 体系架构-过程调用约定
ref: ARM体系结构学习笔记:过程调用标准AAPC、 ARM32调用约定、ARM64调用约定_arm64 传参 结构体-CSDN博客 ARM软件逆向工程入门 01 - ARM调用约定(Calling Convention)_armv7函数调用约定-CSDN博客 ARM学习(17&…...

STM32基于LL库的USART+DMA使用
时隔两年半再次更新LL库,本次带来USART DMA 实现接收不定长。 1、开发思路 使用USART DMA接收不定长的功能的思路是:借助USART的空闲中断、DMA发送完成中断。 打开F103的手册可得知,USART的空闲中断触发条件是在接收完成后触发࿰…...

设计模式06-结构型模式1(适配器/桥接/组合模式/Java)
#1024程序员节|征文# 4.1 适配器模式 结构型模式(Structural Pattern)的主要目的就是将不同的类和对象组合在一起,形成更大或者更复杂的结构体。结构性模式的分类: 类结构型模式关心类的组合,由多个类…...

【损害和风险评估&坑洼】路面坑洼检测系统源码&数据集全套:改进yolo11-DCNV3
改进yolo11-DLKA等200全套创新点大全:路面坑洼检测系统源码&数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.24 注意:由于项目一直在更新迭代,上面“1.图片效果展示”和“2.视频效果展示”展示的系统图片或者视频可…...

GenAI 生态系统现状:不止大语言模型和向量数据库
自 20 个月前 ChatGPT 革命性的推出以来,生成式人工智能(GenAI)领域经历了显著的发展和创新。最初,大语言模型(LLMs)和向量数据库吸引了最多的关注。然而,GenAI 生态系统远不止这两个部分&#…...
gitlab 配置ssh keys
settings -- 终端配置: git config --global user.email "yxthotmail.cm" 配置gitlab 账号邮箱 git config --global user.name "xt.yao" 配置gitlab账号用户名 生成SSH key,输入命令ssh-keygen -t rsa,一直按回车…...

小程序开发实战:PDF转换为图片工具开发
目录 一、开发思路 1.1 申请微信小程序 1.2 编写后端接口 1.3 后端接口部署 1.4 微信小程序前端页面开发 1.5 运行效果 1.6 小程序部署上线 今天给大家分享小程序开发系列,PDF转换为图片工具的开发实战,感兴趣的朋友可以一起来学习一下!…...

我有两台120kw充电桩一天能赚多少钱
(当前是理想状态下,当然还要看场地费用,还有物业,变压器,等等) ———————————————————— ———————————————————— 要计算两台120kW充电桩能赚多少钱,我们…...

深入了解 Android 中的命名空间:`xmlns:tools` 和其他常见命名空间
在 Android 开发中,xmlns (.xml的namespace)命名空间是一个非常重要的概念。通过引入不同的命名空间,可以使用不同的属性来设计布局、设置工具属性或者支持自定义视图等。除了 xmlns:tools 以外,还有很多常见的命名空间…...

stable-zero123模型构建指南
一、介绍 stabilityai出品,能够对有简单背景的物体进行三维视角图片的生成,简单来说也就是通过调整变换观察的视角生成对应视角的图片。 本项目通过comfyui实现。 二、容器构建说明 1. 部署ComfyUI (1)使用命令克隆ComfyUI g…...
算法题解记录32+++最长连续序列(百题筑基)
你们好,我是蚊子码农,好久不见。由于秋招求职的繁琐事情,我有很长一段时间没更新博客,希望我的粉丝们能够谅解。 秋招我拿到了一些offer,最终决定去一个主要做“网络安全”业务的公司工作,也许明天会更好&a…...

全球知名度最高的华人起名大师颜廷利:世界顶级思想哲学教育家
全国给孩子起名最好的大师颜廷利教授在其最新的哲学探索中,提出了《升命学说》这一前沿理论观点,该理论不仅深刻地回应了古今中外众多哲学流派和思想体系的精髓,还巧妙地融合了实用主义、理想主义以及经验主义的核心理念。通过这一独特的视角…...
Flink Rest API
REST API | Apache Flink Flink官网API 通过curl 或者Rest API工具测试web UI对应的接口返回信息 Flink 提交yarn任务 ./bin/flink run -t yarn-per-job historyServer ../bin/historyserver.sh start...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...