手动依赖项注入 在不使用任何库的情况下,遵循依赖项注入 (DI) 的最佳实践方案来 手动 创建一个应用级别作用域 的 CoroutineScope,通常会在 Application 类中添加一个 CoroutineScope 当创建其他对象时,手动将相同的 CoroutineScope 实例分发到这些对象中。 如果使用 Hilt 的行话,可以说成我们添加了一个 CoroutineScope 绑定,至此,Hilt 就知道如何提供 CoroutineScope 实例了。 然而,上述代码片段仍可以优化。 应用级别作用域限定符 虽然我们目前不需要 CoroutineScope 的多个绑定 (未来我们可能需要像 UserCoroutineScope这样的协程作用域),但是向应用级别 CoroutineScope = CoroutineScope(SupervisorJob() + defaultDispatcher) } 由于 MyRepository 依赖该 CoroutineScope,因而可以非常清晰地知道
协程中的一些关键名称(例如:Job、Coroutine、Dispatcher、CoroutineContext与CoroutineScope)它们之间到底是怎么样的关系? CoroutineScope CoroutineScope是什么? 它们都实现了CoroutineScope接口。 public interface CoroutineScope { /** * The context of this scope. 我们也可以不使用lifecycleScope,自己实现一个CoroutineScope,让它在Activity达到同样的效果。 本篇文章主要介绍了CoroutineScope的作用与Job的相关状态演化与运用。希望对学习协程的伙伴们能够有所帮助,敬请期待后续的协程分析。
文章目录 一、CoroutineScope#produce 构造生产者协程 1、CoroutineScope#produce 函数原型 2、代码示例 二、CoroutineScope#actor 构造消费者协程 1、CoroutineScope#actor 函数原型 2、代码示例 一、CoroutineScope#produce 构造生产者协程 ---- 通过 CoroutineScope#produce * * 协程上下文继承自这个[CoroutineScope]。可以使用[context]参数指定其他上下文元素。 * 父作业也继承自[CoroutineScope],但它也可以被重写 * 使用相应的[context]元素。 #actor 构造消费者协程 ---- 通过 CoroutineScope#actor 函数 , 可以快速构造一个 消费者协程 ; 1、CoroutineScope#actor 函数原型 CoroutineScope
在Kotlin的协程世界中,我们经常会遇到coroutineScope,CoroutineScope,supervisorScope和withContext这些概念。 在Kotlin中,我们可以使用CoroutineScope接口或coroutineScope和supervisorScope函数来定义协程作用域。 二、用法对比 2.1 coroutineScope vs CoroutineScope 首先,我们来看看coroutineScope和CoroutineScope。 ) println("Task from CoroutineScope") } println("CoroutineScope is over") } 2.2 coroutineScope coroutineScope和CoroutineScope都定义了协程的作用域,但它们的使用方式和目的有所不同。
文章目录 一、结构化并发 二、协程作用域构建器 ( runBlocking 函数 | coroutineScope 函数 ) 二、协程作用域构建器 ( coroutineScope 函数 | supervisorScope 函数 ) ---- 结构化并发 通过 协程作用域 CoroutineScope 管理协程任务 ; 协程作用域 构建器 是 结构化并发 的重要组成部分 ; 常用的 协程作用域构建器 有 coroutineScope suspend fun <R> coroutineScope(block: suspend CoroutineScope.() -> R): R 共同点 : 这两个 协程作用域构建器 构建的协程 都会等待 函数 由于是 挂起函数 , 只能在 协程体 中使用 ; 该 coroutineScope 协程作用域 将 子协程 job0 和 job1 包裹起来 , coroutineScope 作用域需要等待 { // 该 coroutineScope 协程作用域 将 子协程 job0 和 job1 包裹起来 // coroutineScope
借助 scope 来取消任务 在 Kotlin 中,定义协程必须指定其 CoroutineScope 。CoroutineScope 可以对协程进行追踪,即使协程被挂起也是如此。 CoroutineScope 会跟踪所有协程,并且可以取消由它所启动的所有协程。 coroutineScope 构造器和 CoroutineScope 这两个的区别只是一个字符之差,但它们却是完全不同的东西。 我们目前对这个 CoroutineScope 一无所知,它可能是viewModelScope 或者是其他地方定义的某个 CoroutineScope,但不管怎样,coroutineScope 构造器都会使用它作为其创建新的 如果一个通过 coroutineScope 创建的协程抛出了异常,coroutineScope 会将其抛给调用方。
CoroutineScope CoroutineScope 会追踪每一个您通过 launch 或者 async 创建的协程 (这两个是 CoroutineScope 的扩展函数)。 当您希望在应用程序的某一个层次开启或者控制协程的生命周期时,您需要创建一个 CoroutineScope。 当创建 CoroutineScope 的时候,它会将 CoroutineContext 作为构造函数的参数。 在下面的代码片段中,除了通过 CoroutineScope 创建新的协程,来看看如何在协程中创建更多协程: val scope = CoroutineScope(Job() + Dispatchers.Main 在我们这个系列的第三部分中,CoroutineScope 会有另外一个 Job 的实现称为 SupervisorJob 被包含在其 CoroutineContext 中,该对象改变了 CoroutineScope
实例对象 , 传入 调度器 : // 创建协程作用域 val coroutineScope = CoroutineScope(Dispatchers.Default) 调用 协程作用域的 CoroutineScope = CoroutineScope(Dispatchers.Default) val job0 = coroutineScope.launch { = CoroutineScope(Dispatchers.Default) val job0 = coroutineScope.launch { = CoroutineScope(Dispatchers.Default) val job1 = coroutineScope.launch { = CoroutineScope(Dispatchers.Default) val job1 = coroutineScope.launch {
通过该 CoroutineScope 创建的所有协程都将被取消。 在某些场景下,这样的异常传播是适用的。但是,也有一些场景并不合适。 想象一个 UI 相关的 CoroutineScope ,它负责处理用户交互。如果它的一个子协程抛出了异常,那么这个 UI Scope 将被取消。 你可以这样创建协程作用域 val uiScope = CoroutineScope(SupervisorJob()) ,来保证不传播异常。 同样的行为准则也适用于协程作用域构建器 coroutineScope 和 supervisorScope 。 ⚠️ 通过 coroutineScope 构建器或者由其他协程启动的协程抛出的异常,不会被 try/catch 捕获!
文章目录 一、MainScope 协程作用域 二、取消 MainScope 协程作用域 三、Activity 实现 CoroutineScope 协程作用域接口 常见的 CoroutineScope 协程作用域 ; 这是使用了设计模式中的 工厂模式 , 生产一个 协程作用域 实例对象 ; 之后的 协程操作都要定义在该协程作用域中 ; public fun MainScope(): CoroutineScope * / public fun CoroutineScope.cancel(cause: CancellationException? 协程作用域接口 ---- 通过委托方式 , 继承 CoroutineScope 接口 , public interface CoroutineScope { public val coroutineContext : CoroutineContext } 即可 将整个 协程作用域 委托给 Activity , class MainActivity : AppCompatActivity(), CoroutineScope
= CoroutineScope(Dispatchers.Default) val job1 = coroutineScope.launch { = CoroutineScope(Dispatchers.Default) val job1 = coroutineScope.launch { * 如果作用域的[coroutineContext][CoroutineScope.coroutineContext]中没有[Job],则此函数不做任何事情。 = CoroutineScope(Dispatchers.Default) val job1 = coroutineScope.launch { = CoroutineScope(Dispatchers.Default) val job1 = coroutineScope.launch {
: 1、通过CoroutineScope创建 2、在协程中创建 第一种方式,首先如何通过CoroutineScope创建? val scope = CoroutineScope(Job() + Dispatchers.Main) @Suppress("FunctionName") public fun CoroutineScope 就可以实例出来一个CoroutineScope对象了。 val job = scope.launch {①/\* this: CoroutineScope \*/ // 新的协程会将 CoroutineScope 作为父级 ,在launch里面创建 1、有一个元素job,控制协程的生命周期 2、剩余的元素会从CoroutineContext 的父级继承,该父级可能是另外一个协程或者创建该协程的 CoroutineScope 2、CoroutineScope
异常会到达层级的根部,而且当前 CoroutineScope 所启动的所有协程都会被取消。 假设您的应用中有一个与 UI 关联的 CoroutineScope,用于处理与用户的交互 。 您可以使用这样的代码创建一个 CoroutineScope: val uiScope = CoroutineScope(SupervisorJob()),这样就会像下图中展示的那样,在协程运行失败时也不会传播取消操作 未被捕获的异常一定会被抛出,无论您使用的是哪种 Job 使用 coroutineScope 和 supervisorScope 也有相同的效果。 ⚠️ 在 coroutineScope builder 或在其他协程创建的协程中抛出的异常不会被 try/catch 捕获!
v=w0kfnydnFWI&feature=emb_logo CoroutineScope(协程作用域) CoroutineScope 可以帮助你追踪任何通过 launch 和 async 启动的协程。 它们都是 CoroutineScope 的扩展函数。正在运行的协程可以通过调用 scope.cancel() 在任意时间点停止。 无论你在 App 的任何页面启动协程,并控制其生命周期,都应该创建 CoroutineScope 。 由于 CoroutineScope 可以创建协程,并且你可以在一个协程内部创建多个协程。这就形成了一个隐式的层级结构。 在下面的代码中,除了使用 CoroutineScope 创建新协程之外,还展示了如何在一个协程中创建多个协程。
ViewModel的作用域 CoroutineScope 会跟踪所有它创建的协程。因此,当你取消一个作用域的时候,所有它创建的协程也会被取消。 创建一个新作用域,并传入一个将在 onCleared() 方法中取消的 SupervisorJob,这样你就在 ViewModel 中添加了一个 CoroutineScope。 get() { val scope: CoroutineScope? CoroutineScope 就存储在这里。如果我们看下代码,getTag(JOB_KEY) 方法试图从中取回作用域。 如果取回值为空,它将以前文提到的方式创建一个新的 CoroutineScope 并将其加标签存储。
.() -> T): T CoroutineScope.launch 通过一个协程作用域的扩展方法launch启动一个协程,不会阻塞调用它的线程,返回值是Job。 = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job CoroutineScope.async 通过一个协程作用域的扩展方法 CoroutineScope(Dispatchers.IO).launch {} 是在指定的 CoroutineScope 中启动一个协程,通常情况下应该手动创建 CoroutineScope 对象,并确保在合适的时机取消该 CoroutineScope 以避免内存泄漏。 因此,建议在大多数情况下使用 CoroutineScope 来启动协程,以便更好地管理协程的生命周期。
launch 构建器示例 4、Deferred 类 5、async 构建器示例 二、协程构建器示例 一、协程构建器 ---- 1、协程构建器概念 协程 需要 协程构建器 来启动 , 协程构建器 就是 CoroutineScope 协程作用域的两个扩展函数 ; 协程构建器 : 协程有两种构建器 , 调用 CoroutineScope 协程作用域 的如下两个构建起可启动协程 ; launch 构建器 : 返回 Job 实例对象 , 该协程任务没有返回值 ; launch 函数是 CoroutineScope 协程作用域 类的扩展函数 ; public fun CoroutineScope.launch( context: 协程作用域 类的扩展函数 ; public fun <T> CoroutineScope.async( context: CoroutineContext = EmptyCoroutineContext , start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T ): Deferred
coroutineScope.launch { // 执行异步操作,例如网络请求或数据库查询 } } 创建协程作用域有两种方式 val coroutineScope = rememberCoroutineScope() 或者 val coroutineScope = CoroutineScope(Dispatchers.Main) 使用协程构建器: 在协程作用域中使用协程构建器 val coroutineScope = rememberCoroutineScope() coroutineScope.launch { // 在后台线程执行耗时操作 val result 协程作用域 CoroutineScope(Dispatchers.Main) 和 rememberCoroutineScope()的区别: CoroutineScope(Dispatchers.Main 每次调用 CoroutineScope(Dispatchers.Main) 都会创建一个新的协程作用域对象,这意味着它可能在每次调用时创建新的作用域,而不考虑之前是否已存在作用域。
文章目录 一、协程构建器 CoroutineScope.async 函数 1、协程构建器 CoroutineScope.async 函数参数分析 2、协程构建器 CoroutineScope.async 函数 ---- 1、协程构建器 CoroutineScope.async 函数参数分析 协程构建器 CoroutineScope.async 函数中 , public fun <T> CoroutineScope.async .() -> T 是协程作用域代码块 , 其中是协程任务代码 ; 2、协程构建器 CoroutineScope.async 函数参数原型 CoroutineScope.async 函数原型 : 机翻文档 * 它用于[launch][CoroutineScope的' start '参数中。发射],[异步][CoroutineScope。以及其他协程构建器函数。 * * 有关详细信息,请参阅相应协程构建器的文档 * (如[发射][CoroutineScope。和[async][CoroutineScope.async])。
尽量少用 GlobalScope GlobalScope 是 CoroutineScope 的实现类。 我们以前使用过的 launch、async 函数都是 CoroutineScope 的扩展函数。 GlobalScope 没有绑定任何 Job 对象,它用于构建最顶层的协程。 接下来,通过一个自定义 CoroutineScope ,并且它的 CoroutineContext 与 Job 对象相加,Job 对象可以直接管理该协程。 val job: Job = Job() val scope = CoroutineScope(Dispatchers.Default+job) fun doSomething(): Deferred ,由该 CoroutineScope 创建的 Coroutines 即使抛出异常,依然能够捕获,那将是多么的理想。