在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 { // 在这里执行你的操作,当协程完成时会被调用,无论它是正常完成还是异常完成 } }