Kotlin协程作用域
管理作用域CoroutineScope
及其接口实现类的的所有协程
启动协程
线程sleep
期间,不让出线程使用权,阻塞线程,sleep
时间一到,拿回线程使用权 协程delay
期间,让出线程使用权,并不阻塞线程,执行其他协程(如果有)或者执行线程协程作用域后的代码,delay
时间一到,拿回线程使用权
fun main ( ) {
println ( "Main thread start" )
val scope = CoroutineScope ( Dispatchers. Default)
scope. launch {
println ( "defaultScope start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
println ( "defaultScope end" )
}
println ( "Main thread is working..." )
Thread. sleep ( 1500L )
println ( "Main thread end" )
}
Main thread start
Main thread is working.. .
defaultScope start DefaultDispatcher- worker- 1
defaultScope end
Main thread end
取消协程
发送取消信号到协程作用域中所有协程,作用域中必须有delay
或者挂起函数才能检测取消信号并取消
fun main ( ) {
println ( "main thread start" )
val scope = CoroutineScope ( Dispatchers. Default)
scope. launch {
for ( count in 1 .. 5 ) {
delay ( 1000L )
println ( "Coroutine is still working... $ count " )
}
}
println ( "Main thread is working..." )
Thread. sleep ( 3000L )
println ( "Main thread is going to cancel the coroutine..." )
scope. cancel ( )
Thread. sleep ( 3000L )
println ( "main thread end" )
}
main thread start
Main thread is working.. .
Coroutine is still working.. . 1
Coroutine is still working.. . 2
Main thread is going to cancel the coroutine.. .
main thread end
持有CoroutineContext
上下文对象
调用度Dispatcher
:指定协程执行的线程或者线程池 异常处理器ExceptionHandler
:捕获协程中发生的异常 作业Job
:获取协程的生命周期和状态 协程名称CoroutineName
:用于调试和跟踪
public interface CoroutineScope {
public val coroutineContext: CoroutineContext
}
顶层协程作用域GlobalScope
在整个应用程序生命周期内都存在,应用销毁才释放所持有的资源 生命周期短的组件销毁时,如果Activity/Fragment
持有GlobalScope
,Activity/Fragment
销毁时,如果没有取消GlobalScope
,GlobalScope
持有Activity/Fragment
,导致内存泄漏 EmptyCoroutineContext
不包含任何Job
和Dispatcher
信息
public object GlobalScope : CoroutineScope {
override val coroutineContext: CoroutineContext
get ( ) = EmptyCoroutineContext
}
const val TAG = "Yang"
class MainActivity : AppCompatActivity ( ) {
private var globalJob : Job? = null
override fun onCreate ( savedInstanceState: Bundle? ) {
super . onCreate ( savedInstanceState)
setContentView ( R. layout. activity_main)
Log. e ( TAG, "onCreate start" )
globalJob = GlobalScope. launch {
delay ( 10000L )
Log. e ( TAG, "GlobalScope is still working...." )
}
Log. e ( TAG, "onCreate end" )
}
override fun onDestroy ( ) {
super . onDestroy ( )
Log. d ( TAG, "onDestroy" )
}
}
onCreate start
onCreate end
onDestroy
GlobalScope is still working.. ..
主协程作用域MainScope
协程作用域中代码在Main
线程中执行,由调度器Dispatchers.Main
指定 协程作用域中启动的多个协程,其中一个协程抛出异常,MainScope
中所有协程都会被取消,其工作类型SupervisorJob
失效
public fun MainScope ( ) : CoroutineScope = ContextScope ( SupervisorJob ( ) + Dispatchers. Main)
class MainActivity : AppCompatActivity ( ) {
private val handler = CoroutineExceptionHandler { _, exception ->
Log. d ( TAG, "Caught $ exception " )
}
private val mainScope = MainScope ( ) + handler
override fun onCreate ( savedInstanceState: Bundle? ) {
super . onCreate ( savedInstanceState)
setContentView ( R. layout. activity_main)
mainScope. launch {
val exceptionJob = launch {
Log. d ( TAG, "Exception job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
throw Exception ( "An error occurred in exception job." )
Log. d ( TAG, "Exception job end" )
}
val normalJob = launch {
Log. d ( TAG, "Normal job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
Log. d ( TAG, "Normal job end" )
}
}
}
override fun onDestroy ( ) {
super . onDestroy ( )
mainScope. cancel ( )
}
}
Exception job start main
Normal job start main
Caught java. lang. Exception: An error occurred in exception job.
一般协程作用域的实现类CoroutineScope
构造函数中传入调度器Dispatchers
,工作类型Job
,协程名字CoroutineName
,协程异常处理器CoroutineExceptionHandler
调度器为Dispatchers.IO
,工作类型为SupervisorJob
,父协程中一个协程抛出异常,不会影响父协程和其他协程执行 调度器为Dispatchers.Main
,工作类型为SupervisorJob
,父协程中一个协程抛出异常,父协程会取消,其他协程也会取消
class MainActivity : AppCompatActivity ( ) {
private var parentScope : CoroutineScope ? = null
override fun onCreate ( savedInstanceState: Bundle? ) {
super . onCreate ( savedInstanceState)
setContentView ( R. layout. activity_main)
parentScope = CoroutineScope ( Dispatchers. IO +
SupervisorJob ( ) +
CoroutineName ( "Yang Coroutine" ) +
CoroutineExceptionHandler { coroutineContext, throwable ->
Log. d ( TAG, "Caught $ throwable " )
} )
parentScope? . launch {
val exceptionJob = launch {
Log. d ( TAG, "Exception job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
throw Exception ( "An error occurred in exception job." )
Log. d ( TAG, "Exception job end" )
}
val normalJob = launch {
Log. d ( TAG, "Normal job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
Log. d ( TAG, "Normal job end" )
}
}
}
override fun onDestroy ( ) {
super . onDestroy ( )
parentScope. cancel ( )
}
}
Exception job start DefaultDispatcher- worker- 4
Normal job start DefaultDispatcher- worker- 4
Normal job end
Caught java. lang. Exception: An error occurred in exception job.
supervisorScope
自我牺牲协程作用域
一个子协程的抛出异常,不会影响父协程执行,从而不会影响其余子协程的执行
class MainActivity : AppCompatActivity ( ) {
private var globalJob : Job ? = null
override fun onCreate ( savedInstanceState: Bundle? ) {
super . onCreate ( savedInstanceState)
setContentView ( R. layout. activity_main)
globalJob = GlobalScope. launch {
supervisorScope {
val exceptionJob = launch {
Log. d ( TAG, "Exception job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
throw Exception ( "An error occurred in exception job." )
Log. d ( TAG, "Exception job end" )
}
val normalJob = launch {
Log. d ( TAG, "Normal job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
Log. d ( TAG, "Normal job end" )
}
}
}
}
override fun onDestroy ( ) {
super . onDestroy ( )
globalJob? . cancel ( )
}
}
Exception job start DefaultDispatcher- worker- 2
Normal job start DefaultDispatcher- worker- 2
Normal job end
coroutineScope
同归于尽协程作用域
一个子协程的抛出异常,取消父协程执行,取消其余子协程的执行
class MainActivity : AppCompatActivity ( ) {
private var globalJob : Job ? = null
override fun onCreate ( savedInstanceState: Bundle? ) {
super . onCreate ( savedInstanceState)
setContentView ( R. layout. activity_main)
globalJob = GlobalScope. launch {
coroutineScope {
val exceptionJob = launch {
Log. d ( TAG, "Exception job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
throw Exception ( "An error occurred in exception job." )
Log. d ( TAG, "Exception job end" )
}
val normalJob = launch {
Log. d ( TAG, "Normal job start ${ Thread. currentThread ( ) . name } " )
delay ( 1000L )
Log. d ( TAG, "Normal job end" )
}
}
}
}
override fun onDestroy ( ) {
super . onDestroy ( )
globalJob? . cancel ( )
}
}
Exception job start DefaultDispatcher- worker- 1
Normal job start DefaultDispatcher- worker- 2