在Kotlin中,CoroutineScope 提供了一种方便的方式来管理协程的生命周期,当你在一个协程作用域中启动一个新的协程时,这个新的协程会在该作用域结束时自动取消,在某些情况下,你可能需要从非协程环境(如普通的函数或回调)中启动一个阻塞的协程,这时可以使用launch 函数配合Dispatchers.IO 来避免主线程被阻塞。
1. 使用GlobalScope.launch
GlobalScope 是一个全局的协程作用域,它永远不会被取消,这意味着你可以在任何地方启动一个协程,而不用担心作用域的生命周期问题,由于GlobalScope 是全局性的,它可能会引起内存泄漏,特别是在长时间运行的应用中,你应该尽量避免使用GlobalScope,除非你有明确的理由。
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
GlobalScope.launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
}2. 使用runBlocking
如果你需要在当前的线程中等待协程完成,你可以使用runBlocking 函数,这会阻塞当前线程,直到协程完成,这种方法通常用于测试或在主函数中启动协程。
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.Dispatchers
fun main() = runBlocking {
launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
}3. 使用withContext
如果你需要在当前协程中切换到不同的调度器,你可以使用withContext 函数,这不会阻塞当前线程,而是将协程挂起,直到新的调度器上的操作完成。
import kotlinx.coroutines.withContext
import kotlinx.coroutines.Dispatchers
suspend fun main() {
withContext(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
}4. 使用async 和await
如果你需要并发地执行多个任务,并且需要它们的结果,你可以使用async 和await 函数。async 函数会启动一个新的协程,并立即返回一个Deferred 对象,你可以使用await 函数来等待这个Deferred 对象的结果,而不阻塞当前线程。
import kotlinx.coroutines.async
import kotlinx.coroutines.await
import kotlinx.coroutines.Dispatchers
suspend fun main() {
val result = async(Dispatchers.IO) {
// 在这里执行你的耗时操作,并返回结果
}
val resultValue = result.await() // 等待结果,但不阻塞当前线程
}5. 使用CoroutineScope 和Job
如果你需要更细粒度的控制协程的生命周期,你可以创建一个自定义的CoroutineScope,你可以使用SupervisorJob 来确保子协程在父协程取消时不会被取消。
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
val scope = CoroutineScope(SupervisorJob())
scope.launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
}6. 使用ensureActive
如果你需要在协程中检查它是否仍然活跃,你可以使用ensureActive 函数,如果协程已经被取消,它会抛出CancellationException。
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
launch(Dispatchers.IO) {
ensureActive() // 检查协程是否仍然活跃
// 在这里执行你的耗时操作
}
}7. 使用joinJob
如果你需要等待一个协程完成,并且不需要它的结果,你可以使用joinJob 函数,这会阻塞当前线程,直到协程完成。
import kotlinx.coroutines.joinJob
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
val job = launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
job.joinJob() // 等待协程完成
}8. 使用cancelAndJoin
如果你需要取消一个协程,并等待它完成,你可以使用cancelAndJoin 函数,这会取消协程,并等待它完成。
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
fun main() {
val job = launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
job.cancelAndJoin() // 取消协程并等待它完成
}9. 使用isActive
如果你需要检查一个协程是否仍然活跃,你可以使用isActive 属性,如果协程已经被取消,它会返回false。
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
val job = launch(Dispatchers.IO) {
if (isActive) {
// 在这里执行你的耗时操作
} else {
// 协程已经被取消
s}
}
}10. 使用delay
如果你需要在协程中延迟一段时间,你可以使用delay 函数,这会挂起协程,直到指定的时间过去。
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
launch(Dispatchers.IO) {
delay(1000L) // 延迟1秒
// 在这里执行你的耗时操作
}
}11. 使用withTimeout
如果你需要在协程中设置一个超时时间,你可以使用withTimeout 函数,如果超时时间到了,它会取消协程,并抛出TimeoutCancellationException。
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.TimeoutCancellationException
suspend fun main() {
try {
withTimeout(1000L) { // 设置超时时间为1秒
launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
}
} catch (e: TimeoutCancellationException) {
// 处理超时异常
}
}12. 使用onJoin 和onCompleted
如果你需要在协程完成时执行一些操作,你可以使用onJoin 和onCompleted 函数,这些函数会在协程完成时被调用。
import kotlinx.coroutines.onJoin
import kotlinx.coroutines.onCompleted
import kotlinx.coroutines.launch
import kotlinx.coroutines.Dispatchers
suspend fun main() {
val job = launch(Dispatchers.IO) {
// 在这里执行你的耗时操作
}
job.onJoin {
// 在这里执行你的操作,当协程完成时会被调用
}
job.onCompleted {
// 在这里执行你的操作,当协程完成时会被调用,无论它是正常完成还是异常完成
}
} 