Android Kotlin协程入门
Android官方推荐使用协程来处理异步问题。以下是协程的特点:
- 轻量:单个线程上可运行多个协程。协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
- 内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。
- 内置取消支持:取消操作会自动在运行中的整个协程层次结构内传播。
- Jetpack集成:许多Jetpack库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可用于结构化并发。
示例
首先工程中需要引入Kotlin与协程。然后再使用协程发起网络请求。
引入
Android工程中引入Kotlin,参考 Android项目使用kotlin
有了Kt后,引入协程
dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" // 协程
}
启动协程
不同于Kotlin工程直接使用GlobalScope,这个示例在ViewModel中使用协程。需要使用viewModelScope。
下面的CorVm1继承了ViewModel。
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope // 引入
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class CorVm1 : ViewModel() {
companion object {
const val TAG = "rfDevCorVm1"
}
fun cor1() {
viewModelScope.launch { Log.d(TAG, "不指定dispatcher ${Thread.currentThread()}") }
}
}
在按钮的点击监听器中调用cor1()方法,可以看到协程是在主线程中的。
不指定dispatcher Thread[main,5,main]
由于此协程通过viewModelScope启动,因此在ViewModel的作用域内执行。如果ViewModel因用户离开屏幕而被销毁,则viewModelScope会自动取消,且所有运行的协程也会被取消。
launch()方法可以指定运行的线程。可以传入Dispatchers来指定运行的线程。
先简单看一下kotlinx.coroutines包里的Dispatchers,它有4个属性:
Default,默认Main,Android中指定的是主线程Unconfined,不指定线程IO,指定IO线程
都通过点击事件来启动
// CorVm1.kt
fun ioCor() {
viewModelScope.launch(Dispatchers.IO) {
Log.d(TAG, "IO 协程 ${Thread.currentThread()}")
}
}
fun defaultCor() {
viewModelScope.launch(Dispatchers.Default) {
Log.d(TAG, "Default 协程 ${Thread.currentThread()}")
}
}
fun mainCor() {
viewModelScope.launch(Dispatchers.Main) { Log.d(TAG, "Main 协程 ${Thread.currentThread()}") }
}
fun unconfinedCor() {
viewModelScope.launch(Dispatchers.Unconfined) {
Log.d(TAG, "Unconfined 协程 ${Thread.currentThread()}")
}
}
运行log
IO 协程 Thread[DefaultDispatcher-worker-1,5,main]
Main 协程 Thread[main,5,main]
Default 协程 Thread[DefaultDispatcher-worker-1,5,main]
Unconfined 协程 Thread[main,5,main]
从上面的比较可以看出,如果想利用后台线程,可以考虑Dispatchers.IO。Default用的也是DefaultDispatcher-worker-1线程。
模拟网络请求
主线程中不能进行网络请求,我们把请求放到为IO操作预留的线程上执行。一些信息用MutableLiveData发出去。
// CorVm1.kt
val info1LiveData: MutableLiveData<String> = MutableLiveData()
private fun reqGet() {
info1LiveData.value = "发起请求"
viewModelScope.launch(Dispatchers.IO) {
val url = URL("https://www.baidu.com/s?wd=abc")
try {
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "GET"
conn.connectTimeout = 10 * 1000
conn.setRequestProperty("Cache-Control", "max-age=0")
conn.doOutput = true
val code = conn.responseCode
if (code == 200) {
val baos = ByteArrayOutputStream()
val inputStream: InputStream = conn.inputStream
val inputS = ByteArray(1024)
var len: Int
while (inputStream.read(inputS).also { len = it } > -1) {
baos.write(inputS, 0, len)
}
val content = String(baos.toByteArray())
baos.close()
inputStream.close()
conn.disconnect()
info1LiveData.postValue(content)
Log.d(TAG, "net1: $content")
} else {
info1LiveData.postValue("网络请求出错 $conn")
Log.e(TAG, "net1: 网络请求出错 $conn")
}
} catch (e: Exception) {
Log.e(TAG, "reqGet: ", e)
}
}
}
看一下这个网络请求的流程
- 从主线程调用
reqGet()函数 viewModelScope.launch(Dispatchers.IO)在协程上发出网络请求- 在协程中进行网络操作。把结果发送出去。
参考
Android Kotlin协程入门的更多相关文章
- Kotlin协程入门
开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 介绍Kotlin中的协程.用一 ...
- Kotlin协程基础
开发环境 IntelliJ IDEA 2021.2.2 (Community Edition) Kotlin: 212-1.5.10-release-IJ5284.40 我们已经通过第一个例子学会了启 ...
- Kotlin 协程一 —— 全面了解 Kotlin 协程
一.协程的一些前置知识 1.1 进程和线程 1.1.1基本定义 1.1.2为什么要有线程 1.1.3 进程与线程的区别 1.2 协作式与抢占式 1.2.1 协作式 1.2.2 抢占式 1.3 协程 二 ...
- Kotlin协程解析系列(上):协程调度与挂起
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...
- Kotlin协程第一个示例剖析及Kotlin线程使用技巧
Kotlin协程第一个示例剖析: 上一次https://www.cnblogs.com/webor2006/p/11712521.html已经对Kotlin中的协程有了理论化的了解了,这次则用代码来直 ...
- Retrofit使用Kotlin协程发送请求
Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用.本文简单介绍一下Retrofit中协程的使用 导入依赖 app的build文件中加入: impleme ...
- rxjava回调地狱-kotlin协程来帮忙
本文探讨的是在tomcat服务端接口编程中, 异步servlet场景下( 参考我另外一个文章),用rxjava来改造接口为全流程异步方式 好处不用说 tomcat的worker线程利用率大幅提高,接口 ...
- Kotlin协程作用域与构建器详解
在上次我们是通过了这种方式来创建了一个协程: 接着再来看另一种创建协程的方式: 下面用它来实现上一次程序一样的效果,先来回顾一下上一次程序的代码: 好,下面改用runBlocking的方式: 运行一下 ...
- Kotlin协程通信机制: Channel
Coroutines Channels Java中的多线程通信, 总会涉及到共享状态(shared mutable state)的读写, 有同步, 死锁等问题要处理. 协程中的Channel用于协程间 ...
随机推荐
- 有了Swagger2,再也不用为写Api文档头疼了
1.为什么要写Api文档 现在,前后端分离的开发模式已经非常流行,后端开发工程师只负责完成后端接口,前端页面的开发和渲染完全由前端工程师完成. 问题来了,前端工程师怎么知道后端接口的具体定义呢?答案是 ...
- 09.SpringMVC之类型转换
一. 类型转换器 前端传入的值,从表单中传入的值,都是字符串或者是字符串数组的形式传入的,在后端需要进行手动的转换类型,然后才能正确的使用. 框架一般对常见的数据类型的转换进行了封装提供,如字符串转换 ...
- Spring @Order注解的使用
注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响: 1 ...
- css - rem和vw
css - rem和vw 物理像素 物理像素在不同的设备中1px里可以容纳的像素颗粒是不相同的,所以1px这个单位其实也是有N个像素颗粒填充的.同一尺寸屏幕的每个像素点所能容纳的像素颗粒越多显示效果越 ...
- springmvc框架(Spring SpringMVC, Hibernate整合)
直接干货 model 考虑给用户展示什么.关注支撑业务的信息构成.构建成模型. control 调用业务逻辑产生合适的数据以及传递数据给视图用于呈献: view怎样对数据进行布局,以一种优美的方式展示 ...
- java发送短信开发,第三方接口方法
必备的三个jar包Maven有自己去下: commons-logging commons-logging 1.1 commons-httpclient commons-httpclient 3.1 c ...
- jdbc操作mysql(一)
java.sql包 在使用jdbc之前,我们先看看有关操作jdbc会用到的几个类和接口,通过查看官方文档可知 DriverManager:用于管理一组JDBC驱动程序的基本服务,即管理数据库中的所有驱 ...
- LeetCode入门指南 之 动态规划思想
推荐学习labuladong大佬的动态规划系列文章:先弄明白什么是动态规划即可,不必一次看完.接着尝试自己做,没有思路了再回过头看相应的文章. 动态规划一般可以由 递归 + 备忘录 一步步转换而来,不 ...
- JavaScript 特殊字符
代码输出\'单引号\"双引号\&和号\\反斜杠\n换行符\r回车符\t制表符\b退格符\f换页符
- 1.深入TiDB:初见TiDB
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/584 本篇文章应该是我研究的 TiDB 的第一篇文章,主要是介绍整个 ...