Kotlin->Kotlin协程作用域

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...")
	// 主线程阻塞时间必现大于协程作用域中的delay时间,否则delay后的代码无法执行,因为主线程已经执行完
	Thread.sleep(1500L)
	println("Main thread end")
}

// log result
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)  // 等待3s,查看协程是否被取消
	 println("main thread end")
}
 
// log result 
main thread start
Main thread is working...
Coroutine is still working... 1
Coroutine is still working... 2 // 有可能执行到这里,因为第三次循环走到delay函数,不一定能检测取消信号,在第四次循环检测到取消信号,退出协程作用域
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持有GlobalScopeActivity/Fragment销毁时,如果没有取消GlobalScopeGlobalScope持有Activity/Fragment,导致内存泄漏
  • EmptyCoroutineContext不包含任何JobDispatcher信息
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")
//        globalJob?.cancel() 这种方式取消与这个变量绑定的GlobalScope
//        GlobalScope.cancel() 这种方式取消与整个应用绑定的GlobalScope
    }
}

// log result
onCreate start
onCreate end
onDestroy
GlobalScope is still working.... // Activity销毁后,没有取消GlobalScope的执行,后台会一直执行GlobalScope中的代码

主协程作用域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")
    }
    // 给MainScope添加异常处理器,协程中发生异常,没有捕获,应用会报停
    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()
    }
}

// log result 
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()
    }
}

// log result
Exception job start DefaultDispatcher-worker-4
Normal job start DefaultDispatcher-worker-4
Normal job end // 因为传入的工作类型为 SupervisorJob,调度器为Dispatchers.IO
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()
    }
}

// log result
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()
    }
}

// log result
Exception job start DefaultDispatcher-worker-1
Normal job start DefaultDispatcher-worker-2 //应用会报停
  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值