协程相关介绍

一. 协程相关概念

协程不会阻塞当前线程

1. CoroutineDispatcher 协程调度器

Dispatchers.Main - 使用此调度程序可在 Android 主线程上运行协程。
Dispatchers.IO - 此调度程序经过了专门优化,适合在主线程之外执行磁盘或网络 I/O。示例包括使用 Room 组件、从文件中读取数据或向文件中写入数据,以及运行任何网络操作。
Dispatchers.Default - 此调度程序经过了专门优化,适合在主线程之外执行占用大量 CPU 资源的工作。用例示例包括对列表排序和解析 JSON。
Dispatchers.Unconfined-始终和父协程使用同一线程。

2. CoroutineScope 协程作用域

CoroutineScope 接口表示一个协程的作用域,它包含了一个CoroutineContext 对象,用于存储协程的上下文信息。CoroutineScope接口有一些实现类和工厂方法,用于创建不同类型的作用域。例如:
GlobalScope:非阻塞协程构造器,它是一个单例对象,用于创建不受限制的协程。生命周期受整个应用程序的生命周期限制,且不能取消。
CoroutineScope():非阻塞协程构造器,通过 context 参数去管理和控制协程的生命周期声明自己作用域。
MainScope():表示主作用域,它是一个工厂方法,返回一个使用Dispatchers.Main作为上下文的作用域。

3. CoroutineContext 协程上下文

二. 开启协程的方式

1. CoroutineScope.launch

CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
launch 函数是定义在CoroutineScope接口中的一个扩展函数,只能在 CoroutineScope 协程作用域下调用该函数。launch函数会返回一个Job对象,表示协程的任务。如果没有指定上下文,默认情况下,launch函数会使用Dispatchers.Default作为上下文。
launch函数创建的协程有一个特点,就是它不会返回任何结果。这种协程适合执行不需要结果的任务,例如打印消息,更新UI,发送网络请求等。

在 Activity 或者 Fragment 中,可以使用 lifecycleScope.launch 启动协程,这种方式启动的协程会随着LifecycleOwner的销毁而销毁,避免内存泄漏。

activity 中开启协程

lifecycle.coroutineScope.launch { }
或者
lifecycleScope.launch { }

fragment 中开启协程

viewLifecycleOwner.lifecycleScope.launch { }

ViewModel使用协程

viewModelScope.launch启动的协程生命周期跟随ViewModel。一般在调用下层Repository接口时需要启动一个协程,从而能调用Repository层的挂起函数。

2. CoroutineScope.async

async 函数是定义在CoroutineScope接口中的一个扩展函数,只能在 CoroutineScope 协程作用域下调用该函数。该方法返回的是一个 Deferred,Deferred 本身继承自 Job,但是只比job多了一个await方法。await是一个suspend方法,在调用时会挂起调用者所在的协程,直到await的协程完成任务,并且返回。await方法与join方法很像,但是join方法是没有返回值的,只能起到挂起调用者所在协程的作用。

3. runBlocking

使用runBlocking启动的协程任务会阻断当前线程,直到该协程执行结束 runBlocking通常适用于单元测试等场景,业务开发中一般不会用到这个函数。

三. 挂起函数

挂起函数只能在协程中调用,会阻塞当前协程。

withContext

withContext(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T
使用场景:可以在不改变当前协程的情况下切换代码段的执行线程。
1、是一个 suspend 函数,必须在协程中调用。比如原来的协程是在 main 线程里面执行的,通过 withContext 可以让 withContext 里面的代码段切换到指定的其他线程里面工作,此时当前协程会挂起,直到 withContext 内部的代码运行完成才会继续运行 withContext 外部的代码。
2、通过Dispatchers来指定代码块所运行的线程。
3、withContext 方法有返回值,会返回代码块的最后一行的值。
4、如果需要 try/catch 操作需要在 withContext 里面的代码段进行捕获。

四. 协程的取消

协程取消时,也会取消同作用域下的子协程;
协程取消时,该协程下的挂起函数也会被取消,而且是只有“挂起函数”才可以被取消,它会在挂起时检查协程是否被取消,如果取消那么会抛出CancellationException异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值