携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的12天,点击查看活动详情
使用 CoroutineScope
使用GlobalScope的时候,根据情况可能会有所不同,但是在上一篇文章中发现,在使用需要长时间运行的程序时需要谨慎,一定要在不影响内存的情况下使用问题和应用程序的操作。
在本文中,我们将探索 CoroutineScope,
看文档的话,介绍了可以在Android中使用的MainScope()部分,首先来看看示例。
class TestClass {
// 测试类的作用域
val scope = MainScope() // the scope of MyUIClass
// 类销毁的时候进行作用域的取消
fun destroy() {
scope.cancel()
}
/*
* 如果此实例被销毁或该方法中任何启动的协程抛出异常,则所有嵌套协程都将被取消。
*/
fun doSomething() = scope.launch {
// 这样启动在主线程中
}
}
如果你看这个MainScope的内部代码,你可以看到它使用的是CoroutineScope,并且是添加了Android相关的代码。
@Suppress("FunctionName")
public fun MainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatchers.Main)
继续往下查看,MainScope将使用一个继承 CoroutineScope 并仅注入可以使用它的上下文的通用代码。
作为参考,此代码是内部的,不能在外部使用。
internal class ContextScope(context: CoroutineContext) : CoroutineScope {
override val coroutineContext: CoroutineContext = context
override fun toString(): String = "CoroutineScope(coroutineContext=$coroutineContext)"
}
如果你直接继承 CoroutineScope 而不是 MainScope,你应该如下工作。
class TestActivity : AppCompatActivity(), CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + SupervisorJob()
override fun onDestroy() {
super.onDestroy()
cancel()
}
}
最后,您必须完成取消取消的工作。
无条件调用取消并不意味着终止
让我们看一下这段代码并进行预测。
class CoroutineCancel {
@Test
fun testCancel() = runBlocking {
val job = SupervisorJob()
CoroutineScope(Dispatchers.IO).launch {
while (isActive) {
println("Job存活着")
delay(1)
}
}
delay(50)
job.cancel()
delay(500)
}
}
注意:因为这是一个测试代码,所以它会在 500 毫秒后结束。
此代码中的 CoroutineScope 不会终止。
- while 循环不停。
- 退出失败,因为 CoroutineScope 里面没有调用 exit 的代码。
首先,让我们将这段代码中的 while 语句更改为单独的挂起函数。
private suspend fun suspendLoop() = withContext(Dispatchers.IO) {
while (isActive) {
println("Job存活着")
delay(1)
}
}
这也与它仅在 500ms 后终止相同。
然后,你需要修改它,让它可以终止,如果你添加一个作业如下,它会自然终止。
val job = SupervisorJob()
CoroutineScope(Dispatchers.IO + job).launch {
suspendLoop()
}
为了活动小家电,下篇继续搞!