忘记Rxjava吧,你应该试试Kotlin的协程
0.前言
协程以前一直是Kotlin作为实验性的一个库,前些日子发现1.3版本的kotlin relese了协程,所以就找时间研究了一下,本来早就想写这篇文章了,但是因为离职换工作的原因,迟迟未能动笔,这两天终于算搞完了,记录一下我对协程的一些理解。
1.什么是协程
1.1协程定义
我第一次接触协程是在python的教程里,当时廖雪峰在其中的解释还是不错的,这里拿来用来解释一下:子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来接着执行。注意,在一个子程序中中断,去执行其他子程序,不是函数调用,有点类似CPU的中断。
看这个图,协程就是这样,在一个线程中顺序执行的,先执行一段程序,这里用continuation表示,然后遇到suspension point是,程序悬挂,进行下一个continuation子程序的运行。
1.2协程和线程的关系
协程和线程,都能用来实现异步调用,但是这两者之间是有本质区别的
(1)协程是编译器级别的,线程是系统级别的。协程的切换是由程序来控制的,线程的切换是由操作系统来控制的。
(2)协程是协作式的,线程是抢占式的。协程是由程序来控制什么时候进行切换的,而线程是有操作系统来决定线程之间的切换的。
(3)一个线程可以包含多个协程。
(4)Java中,多线程可以充分利用多核cpu,协程是在一个线程中执行。
(5)协程适合io密集型的程序,多线程适合计算密集型的程序(适用于多核cpu的情况)。当你的程序大部分是文件读写操作或者网络请求操作的时候,这时你应该首选协程而不是多线程,首先这些操作大部分不是利用cpu进行计算而是等待数据的读写,其次因为协程执行效率较高,子程序切换不是线程切换,是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。 (6)使用协程可以顺序调用异步代码,避免回调地狱。
2.简单用法
这里我打算模仿一个网络请求,点击button发送网络请求,显示一个progressbar打转,返回结果后一个textview显示结果并隐藏progressbar 先看一下布局文件
<?xml version="1.0" encoding="utf-8"?>
<FrameLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/timeTV"android:layout_width="wrap_content"android:layout_height="wrap_content"/><Buttonandroid:id="@+id/sendBT"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="SEND"android:layout_gravity="center"/><ProgressBarandroid:layout_gravity="center"android:visibility="gone"android:id="@+id/loadingPB"android:layout_width="wrap_content"android:layout_height="wrap_content"/></FrameLayout>
复制代码
一个Button,一个TextView,一个ProgressBar
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)sendBT.setOnClickListener {coroutineSend()}}private fun coroutineSend() {val uiScope = CoroutineScope(Dispatchers.Main)uiScope.launch {loadingPB.visibility = View.VISIBLEval deffer = async(Dispatchers.Default) {getCoroutineResult()}val coroutineResult = deffer.await()timeTV.text = "get $coroutineResult"loadingPB.visibility = View.GONE}}private suspend fun getCoroutineResult(): String {delay(9000L)return "coroutine result"}
}复制代码
首先创建了一个CoroutineScope,所有协程都运行在CoroutineScope中,创建CoroutineScop中传入参数Dispatchers.Main,这是一个协程调度器,它确定了相应的协程在执行时使用一个或多个线程。协程调度器可以将协程的执行局限在指定的线程中,调度它运行在线程池中或让它不受限的运行。 调用launch,就启动了一个协程,launch方法会返回一个job,调用cancel方法可以取消这个协程的进行。可以看到在协程里我们先展示出loadingPB,然后调用async又启动一个协程,同时使用Dispatchers.Default这个协程调度器,它将使协程在执行时使用一个DefaultDispatcher-worker-1线程,这里为什么使用async而没有使用launch,是因为async会返回一个Deferred对象,调用其await方法可以阻塞执行流等到协程执行完毕返回结果,这样可以得到一个返回值,在这个async创建的协程里使用了使用了suspend方法
private suspend fun getCoroutineResult(): String {delay(9000L)return "coroutine result"}
复制代码
先休眠9秒钟,然后返回一个字符串,注意这里这个delay也是suspend方法,一个suspend方法只能在协程或者suspend方法里调用。关于协程还有一些其他的创建和使用方法,有兴趣的可以去看看官方教程。
3.Rxjava VS 协程
协程相对RxJava有什么优点呢?
(1)RxJava堆栈可读性查,一旦出现问题,堆栈信息爆炸,难以定位问题,而协程就可以避免这个问题
(2)协程用同步的方式写异步的代码,美好了生活,方便代码阅读。
(3)协程学习曲线比较平坦,相对于RxJava,协程对初学者更易于学习。
4.最后
这年头用Kotlin来开发android应用确实越来越爽快了,一些新的特性也逐渐加入到Kotlin中,值得更加学习,当然还有Flutter,以后会陆续写几个关于Flutter的文章,毕竟release了,我对它是十分看好的。
关注我的公众号
忘记Rxjava吧,你应该试试Kotlin的协程相关推荐
- Kotlin高级协程
Kotlin高级协程 一.前言 二.先从线程说起 三.协程的设计思想 四.协程特点:优雅的实现移步任务 五.协程基本使用 六.协程和线程相比有什么特点,如何优雅的实现异步任务 一.前言 在文章正式上干 ...
- 【对比Java学Kotlin】协程简史
文章目录 一.概念释义 1.1 协程定义 1.2 与线程的关系 1.3 协程简史 二.种类划分 2.1 按调用栈分类 2.2 按调度方式分类 三.异步编程 3.1 多线程 3.2 回调 3.3 Pro ...
- 十一、kotlin的协程 - 缓存、volatile、内存屏障和cas(四) --- 跑题篇
本章写着写着就跑题了, 又不舍得删除, 新手看 # 协程的共享变量安全问题简单入门和## volatile 不保证原子性部分代码, 其他可以不看, 太乱, 也没用 协程的共享变量安全问题简单入门 在使 ...
- Kotlin的协程与生命周期
文章目录 一.前言 二.引入依赖 三.代码示例 1.基础用法 2.repeatOnLifecycle 3.flowWithLifecycle 4.lifecycle.whenCreated.lifec ...
- 十一、kotlin的协程(一)
theme: Chinese-red 学习的前提 java线程需要大概知道点 协程是线程执行的任务, 协程和用户线程的区别在于, 协程背靠强大的编译器, 协程有专属于协程的调度器和一堆方便好用的函数, ...
- Kotlin中协程理解与实战(一)
Kotlin中协程理解与实战(一) 什么是协程 在Android中协程用来解决什么问题 协程是: suspend -也称为挂起或暂停,用于暂停执行当前协程,并保存所有局部变量: resume -用于让 ...
- Kotlin(3)-协程和操作符重载,Java程序员秋招三面蚂蚁金服
Kotlin 文件和类不存在一对一关系 共生体 继承 修饰符 空指针问题 正文 重难点 协程 想了很久,关于协程的内容,在官网上确实有很多内容,基础知识概念,基本使用,以及 流操作,通道,异常处理,并 ...
- kotlin coroutines 协程教程-入门用法
kotlin coroutines 协程教程-入门用法 Coroutine 协程,是kotlin 上的一个轻量级的线程库,对比 java 的 Executor,主要有以下特点: 更轻量级的 api 实 ...
- Kotlin 之 协程
初识协程,启动取消协程,Flow异步流,协程并发 目录 (一)初识协程 协程是什么? Android中协程解决了什么问题? 协程的挂起与恢复 挂起和阻塞 协程的调度器 Dispatchers 任务泄露 ...
最新文章
- iOS 中 OC项目使用swift第三方工具(OC、swift 混合)
- linux——数据库mariadb的基础操作
- 用配置还用Attribute来实现IoC?
- mybatis主键是在insert前生成还是之后生成
- Aloha:一个略屌的分布式任务调度框架
- (二)建筑物多边形化简系列——多边形点数化简
- jQuery Api 学习(一、jQuery 概念 和 jQuery 文档)
- proDAD Adobe pr cc2020 会声会影视频转场特效制作软件,滤镜特效插件
- cramer定理_克莱姆(cramer)法则及定理简介.ppt
- Python菜鸟入门: 如何在Python中读写文件
- 【PTA】日程安排(多重继承+重载)
- adb 查看屏幕大小_Android adb获取屏幕分辨率
- source insight4.0各种问题处理方法汇总
- Sqli-labs 基本注入篇 (Less1~22)
- C# 使用WebSocket创建聊天室案例
- 邮箱批量导入联系人只需3步
- fluentdpm模型公式_FLUENT中应用DPM模型时双R分布的详细说明
- 几个朋友合伙创业,如何分配股权?
- QGC(QGroundControl)地面站手把手教你改——高德地图的添加和瓦片地图在线资源
- 信息学奥赛一本通-1012:计算多项式的值
热门文章
- Android开发学习笔记:WebView 一
- 编译u-boot时候,make distclean 出现rm:无法删除,****是一个目录
- 非递归一次性加载分类数据到TreeViw
- Java泛型使用需要小心
- C语言中的字符串处理
- 20种看asp源码的方法及工具
- 朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较
- 64位Ubuntu上编译32位程序操作步骤
- avue validate 变为不可编辑_排版技巧——如何用 Word 编辑参考文献
- win7能用的matlab,win7环境下使用matlab7.0(R14)方法