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

kotlin中协程相关

协程

  • 用同步的方式写出异步的效果
  • 协程最重要的是通过非阻塞挂起和恢复实现了异步代码的同步编写方式
  • 挂起函数(suspend)不一定就是在子线程中执行的,但是通常在定义挂起函数时都会为它指定其他线程,这样挂起才有意义
  • 解决多层嵌套回调

协程不是线程,是基于线程封装的库,可以使用协程库提供的API方便的灵活的指定协程中代码执行的线程、切换线程,但不需要接触线程Thread类。类似于Android的AsyncTask或者RxJava的Schedulers,都解决了异步线程切换的问题,然而协程最重要的是通过非阻塞挂起和恢复实现了异步代码的同步编写方式,把原本运行在不通线程的代码写在一个代码块{}里,开起来就像是同步代码。

launchasync之间的区别

launch是一种适用于“发射并忘记”场景的协程构建器,当你不需要等待协程的结果时,它非常有用。它允许你在后台异步执行任务,而不会阻塞主线程,从而提高应用的响应性。

示例:使用launch

fun main() {println("Before launch")// 启动一个协程GlobalScope.launch {delay(1000)println("Inside launch")}println("After launch")Thread.sleep(2000)
}

在上面的示例中,我们使用launch关键字在GlobalScope中启动了一个协程。协程通过delay()函数暂停了1000毫秒,然后打印了"Inside launch"。同时,主线程继续执行。输出结果为:Before launch      After launch     Inside launch

async是一种用于异步执行任务并获取其结果的协程构建器。它返回一个Deferred<T>对象,表示将来可用的值

示例:使用async并发进行网络请求

suspend fun fetchDataFromAPI(url: String): String {// 执行网络请求或其他耗时操作return apiService.fetchData(url)
}suspend fun fetchMultipleData() {val deferredData1 = GlobalScope.async(Dispatchers.IO) {fetchDataFromAPI("https://api.example.com/data1")}val deferredData2 = GlobalScope.async(Dispatchers.IO) {fetchDataFromAPI("https://api.example.com/data2")}val data1 = deferredData1.await()val data2 = deferredData2.await()// 处理获取到的数据```kotlinprocessData(data1, data2)
}

在这个示例中,我们使用async来并发地从多个URL获取数据。每个网络请求被封装在一个单独的async块中,它返回一个Deferred<String>对象。然后我们使用await()来在结果可用时获取结果。获取到数据后,我们可以根据需要进行进一步处理。

总结选择launchasync的关键考虑因素:

  • 当你想要执行一个异步任务而不需要等待结果时,例如进行网络请求或执行后台操作时,使用launch

  • 当你需要并发地执行多个异步任务并获取它们的结果以进行进一步处理时,例如并行网络请求或计算时,使用async

  • 要注意选择合适的上下文来启动协程,以确保正确的线程管理。对于与UI相关的操作,切换到Dispatchers.Main上下文来更新UI。

  • 避免使用长时间运行的操作阻塞主UI线程。使用协程将这些任务转移到后台线程,从而确保响应性用户界面

suspend:withContext(Dispatchers.IO)异步线程

MainScope   需要销毁在onDestroy()方法中:main.cancel()

GlobalScope 全局作用域 默认是异步线程Dispatchers.IO

viewModelScope.launch 默认是主线程Dispatchers.Main

一个页面请求多个接口示例

class SystemViewModel : BaseViewModel() {private val remoteRepository: SystemRemoteRepository by lazy {SystemRemoteRepository()}val page = MutableLiveData<Pagination<Article>>()fun getArticleList() {viewModelScope.launch { //主线程开启一个协程// 网络请求:IO线程val tree: ApiResult<MutableList<Tree>> =RetrofitClient.apiService.getTreeByCoroutines()// 主线程val cid = tree?.data?.get(0)?.idif (cid != null) {// 网络请求:IO线程val pageResult: ApiResult<Pagination<Article>> =RetrofitClient.apiService.getArticleListByCoroutines(0, cid)// 主线程page.value = pageResult.data!!}}}
}/**接口定义,Retrofit从2.6.0版本开始支持协程*/
interface ApiService {/*获取文章树结构*/@GET("tree/json")suspend fun getTreeByCoroutines(): ApiResult<MutableList<Tree>>/*根据数结构下某个分支id,获取分支下的文章*/@GET("article/list/{page}/json")suspend fun getArticleListByCoroutines(@Path("page") page: Int,@Query("cid") cid: Int): ApiResult<Pagination<Article>>
}
在定义接口时,方法前加了个 suspend 关键字,调用接口的时候用viewModelScope.launch {} 包裹。既然可以运行成功,就说明请求接口并不是在主线程中进行的,然而有的同学不信,他在getArticleList() 方法中的任意位置通过 Thread.currentThread() 打印的结果都Thread[main,5,main],这不就是在主线程中调用的吗?上述协程中的代码是在主线程执行没错,但是接口请求的方法却是在子线程中执行的。
原因就在于我们定义接口的时候使用了suspend 关键字,它的意思是挂起、暂停,函数被加了这个标记就称它为挂起函数,需要注意的是,suspend 关键字并没有其他重要的作用,它仅仅标识某个函数是挂起函数,可以在函数中调用其他挂起函数,但是只能在协程中调用它。所以上面两个接口都被定义为挂起函数了,挂起函数只能在协程中调用,那谁是协程?
其实在 kotlin 协程库中是有一个类 AbstractCoroutine 来表示协程的,这个抽象类有很多子类代表不同的协程,但是这些子类都是private 的,并没有暴露给我们,所以你在其他文章中看到别人说
viewModelScope.launch{} 包裹起来的闭包 ( 代码块 ) 就是协程也没问题,但这个代码块的真正意义是协程需要执行的代码。当在协程中调用到挂起函数时,协程就会在当前线程(主线程)中被挂起,这就是协程中著名的 非阻塞式挂起,主线程暂时停止执行这个协程中剩余的代码,注意:暂停并不是阻塞等待(否则会ANR ),而是主线程暂时从这个协程中被释放出来去处理其他 Handler 消息,比如响应用户操作、绘制View 等等。
那挂起函数谁执行?这得看挂起函数内部是否有切换线程,如果没有切换线程当然就是主线程执行了,所以挂起函数不一定就是在子线程中执行的,但是通常在定义挂起函数时都会为它指定其他线程,这样挂起才有意义。比如上面定义的suspend 的请求接口, Retorift 在执行请求的时候就切换到了子线程并挂起主线程,当请求完成(挂起函数执行完毕)返回结果时,会通知主线程:我该干的都干完了,下面的事你接着干吧,主线程接到通知后就会拿到挂起函数返回的结果继续执行协程里面剩余的代码,这叫做协程恢复(resume) 。如果又遇到挂起函数就会重复这个过程,直到协程中的代码被执行完。
通过协程可以彻底去除回调,使用同步的方式编写异步代码。什么是同步调用?调用一个方法能直接拿到方法的返回值,尽管这个方法是耗时的、在其他线程执行的,也能直接得到它的返回值,然后再执行下面的代码,协程不是通过等待的方式实现同步,而是通过非阻塞挂起实现看起来同步的效果。

相关文章:

kotlin中协程相关

协程 用同步的方式写出异步的效果协程最重要的是通过非阻塞挂起和恢复实现了异步代码的同步编写方式挂起函数(suspend)不一定就是在子线程中执行的&#xff0c;但是通常在定义挂起函数时都会为它指定其他线程&#xff0c;这样挂起才有意义解决多层嵌套回调 协程不是线程&…...

(自适应手机端)物流运输快递仓储网站模板 - 带三级栏目

(自适应手机端)物流运输快递仓储网站模板 - 带三级栏目PbootCMS内核开发的网站模板&#xff0c;该模板适用于物流运输网站、仓储货运网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b;自适应手机端&#xff0c;同一个后台…...

Navicat导出表结构到Excel或Word

文章目录 sql语句复制到excel复制到Word sql语句 SELECTcols.COLUMN_NAME AS 字段,cols.COLUMN_TYPE AS 数据类型,IF(pks.CONSTRAINT_TYPE PRIMARY KEY, YES, NO) AS 是否为主键,IF(idxs.INDEX_NAME IS NOT NULL, YES, NO) AS 是否为索引,cols.IS_NULLABLE AS 是否为空,cols.…...

Golang编译优化——稀疏条件常量传播

文章目录 一、概述二、稀疏条件常量传播2.1 初始化worklist2.2 构建def-use链2.3 更新值的lattice2.4 传播constant值2.5 替换no-constant值 一、概述 常量传播&#xff08;constant propagation&#xff09;是一种转换&#xff0c;对于给定的关于某个变量 x x x和一个常量 c …...

人工智能培训讲师咨询叶梓介绍及智能医疗技术与ChatGPT临床应用三日深度培训提纲

1、授课老师简介 叶梓&#xff0c;上海交通大学计算机专业博士毕业&#xff0c;高级工程师。主研方向&#xff1a;数据挖掘、机器学习、人工智能。历任国内知名上市IT企业的AI技术总监、资深技术专家&#xff0c;市级行业大数据平台技术负责人。 长期负责城市信息化智能平台的…...

HCIP(BGP综合实验)--8

一&#xff1a;实验要求 二&#xff1a;实现过程 &#xff08;一&#xff09;配置IP地址&#xff1a; AR1: [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip add 12.1.1.1 24 [AR1-GigabitEthernet0/0/0]int l0 [AR1-LoopBack0]ip add 172.16.0.1 32 [AR1-LoopBack0]int l1 […...

深入理解C++中的Vector容器:用容器构建高效程序

文章目录 vector介绍vector常用的成员函数有关vector定义的函数vector的迭代器使用vector关于空间操作的成员函数vector的增删查改 总结 vector介绍 在C语言的库中包含有公共数据结构的实现&#xff0c;C的这个部分内容就是众所周知的STL&#xff08;标准模版库&#xff09;&a…...

目标检测YOLO实战应用案例100讲-基于深度学习的交通场景多尺度目标检测算法研究与应用(下)

目录 3.2 基于空洞卷积的特征融合模块设计 3.3 改进k-means聚类算法的anchor尺寸优化设计...

react 类组件 和 函数组件 声明周期 对比

React 的类组件和函数组件在生命周期方面存在一些差异。以下是它们之间的对比&#xff1a; 类组件的生命周期 React 类组件的生命周期可以分为三个阶段&#xff1a;挂载、更新和卸载。 1、挂载阶段&#xff1a; constructor()&#xff1a;组件实例化时调用&#xff0c;用于…...

智慧变电站守护者:TSINGSEE青犀AI视频智能管理系统引领行业革新

一、方案概述 随着科技的不断进步&#xff0c;人工智能&#xff08;AI&#xff09;技术已经深入到各个领域。在变电站安全监控领域&#xff0c;引入AI视频监控智能分析系统&#xff0c;可以实现对站内环境、设备状态的实时监控与智能分析&#xff0c;从而提高变电站的安全运行…...

【Ubuntu20.04安装java-8-openjdk】

1 下载 官网下载链接&#xff1a; https://www.oracle.com/java/technologies/downloads/#java8 下载 最后一行 jdk-8u411-linux-x64.tar.gz&#xff0c;并解压&#xff1a; tar -zxvf jdk-8u411-linux-x64.tar.gz2 环境配置 1、打开~/.bashrc文件 sudo gedit ~/.bashrc2、…...

HTTPS对于网站到底价值几何?

现在HTTPS基本上已经是网站的标配了&#xff0c;很少会遇到单纯使用HTTP的网站。但是十年前这还是另一番景象&#xff0c;当时只有几家大型互联网公司的网站会使用HTTPS&#xff0c;大部分使用的都还是简单的HTTP&#xff0c;这一切是怎么发生的呢&#xff1f; 为什么要把网站…...

Docker私有仓库Harbor

简介 Docker私有仓库Harbor是一个开源的、企业级的Docker registry解决方案&#xff0c;它提供了安全、可靠和高效的容器镜像存储和分发服务。以下是关于Docker私有仓库Harbor的详细介绍&#xff1a; 一、Harbor的特点 基于角色的访问控制&#xff08;RBAC&#xff09;&#…...

48. 旋转图像/240. 搜索二维矩阵 II

48. 旋转图像 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 &#xff1a; 输入&#xff1a;matrix [[5,1,9,11],[2,4,…...

wsl安装Xfce桌面并设置系统语言和输入法

一、安装xfce &#xff08;有相关的依赖都会安装&#xff09; sudo apt -y install xfce4 二、 安装远程连接组件 sudo apt install xrdp -y 并重新启动 Xrdp 服务&#xff1a; sudo systemctl restart xrdp 本地windows系统中请按 winR 键 呼出运行 在运行中输入 mstsc…...

短信清空了!华为手机短信删除了怎么恢复?

“有没有人知道这是怎么回事呀&#xff0c;原先有一千多条未读一直放着没管&#xff0c;昨天根本没打开短信这个软件&#xff0c;今晚突然发现只剩一条了&#xff0c;是华为手机自动清理了吗&#xff01;到底该怎么恢复呀&#xff1f;我真崩溃&#xff01;” 在日常生活中&…...

Linux实现Flappy bird项目

目录 1、项目介绍 2、功能总结 3、前期准备 3.1 Ncurses库 3.2 信号机制 3.2.1 设置信号响应方式 3.2.2 设置定时器 4、代码实现 4.1 头文件引用及变量、函数定义 4.2 主函数 4.3 curses初始化 4.4 设置定时器 4.5 定时器响应函数 4.6 小鸟控制相关函数 4…...

【python量化交易】qteasy使用教程07——创建更加复杂的自定义交易策略

创建更加复杂的自定义交易策略 使用交易策略类&#xff0c;创建更复杂的自定义策略开始前的准备工作本节的目标继承Strategy类&#xff0c;创建一个复杂的多因子选股策略策略和回测参数配置&#xff0c;并开始回测 本节回顾 使用交易策略类&#xff0c;创建更复杂的自定义策略 …...

SpringBoot整合SpringScurity权限控制(菜单权限,按钮权限)以及加上SSH实现安全传输

文章目录 项目地址&#xff1a; 一、md5 与 先进的哈希算法的区别1.1. 安全性问题1.2. 设计目的1.3. 功能特性1.4. 适用性1.5. 总结 二、数据传输安全和数据加密实现&#xff1a;2.1 生成证书&#xff1a;2.2、在springboot中进行集成2.2.1 配置证书&#xff1a;2.2.2. 强制使用…...

力扣每日一题119:杨辉三角||

题目 简单 给定一个非负索引 rowIndex&#xff0c;返回「杨辉三角」的第 rowIndex 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: rowIndex 3 输出: [1,3,3,1]示例 2: 输入: rowIndex 0 输出: [1]示例 3: 输入: rowIndex 1 输出…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...