https://www.youtube.com/watch?v=VWlwkqmTLHc&list=PLQkwcJG4YTCQcFEPuYGuv54nYai_lwil_&index=11
协程总结
抓不到的异常
如果我们在launch外面try catch 意图捕获异常的话
//无法捕获异常导致奔溃
private fun cannotCatchException() {
lifecycleScope.launch {
try {
//外面catch不到的
launch {
//只能在这里面try catch,直接捕获
throw Exception()
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
如果不是在抛出异常的地方直接捕获异常,那么在外面是捕获不到的,会直接导致应用奔溃
asyn不会奔溃
如果async中发生了异常,如果没有调用await,则程序不会奔溃
private fun asyncWonCrash() {
lifecycleScope.async {
val string = async {
delay(1000)
throw Exception("error")
}
}
}
我们在async中直接抛出异常,但是应用没有奔溃
但如果在launch中运行,需要再await的地方添加捕获,不然程序奔溃
private fun asyncWonCrash() {
val result = lifecycleScope.async {
val string = async {
delay(1000)
throw Exception("error")
"result"
}
println("linlian"+string.await())
}
lifecycleScope.launch {
try {
result.await()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
当时如果只是看到这里,以为就结束了!!!!
no,上面的这个异常捕获,有一个很大的陷阱,之前的文章也有提到
就是我们可能吧 cancellation exception也捕获了,导致协程任务无法取消!!!!
那一般是怎么处理了,可以根coroutinescope添加coroutineexception handler
private val exceptionHander = CoroutineExceptionHandler { ctx, throwale ->
println("handle exception $throwale")
}
private fun exceptionHandlerdemo() {
lifecycleScope.launch(exceptionHander) {
launch {
throw Exception("error")
}
}
}
这样内部子任务的异常都可以被捕获
协程的某个子任务异常了,那其他的任务会怎样呢?
那这个和所在的scope的类型有关,如果是个普通的sceop
当有一个子协程异常了,其他的协程也取消了
private fun differentScope() {
CoroutineScope(Dispatchers.Main).launch(exceptionHander) {
launch {
delay(300)
throw Exception("linlian 1 failed")
}
launch {
delay(500)
println("linlian 2 success")
}
}
}
但是像viewmodescope这些,还有globalscope,一般我们一个子协程异常,是不会影响到其他的协程的,这个是什么原因呢
viewmodel的源码中
val ViewModel.viewModelScope: CoroutineScope
get() {
val scope: CoroutineScope? = this.getTag(JOB_KEY)
if (scope != null) {
return scope
}
return setTagIfAbsent(JOB_KEY,
CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate))
}
SupervisorJob()
Creates a supervisor job object in an active state. Children of a supervisor job can fail independently of each other.
互不影响
private fun differentScope() {
CoroutineScope( Dispatchers.Main).launch(exceptionHander) {
supervisorScope {
launch {
delay(300)
throw Exception("linlian 1 failed")
}
launch {
delay(500)
println("linlian 2 success")
}
}
}
}
所以加上 supervisorScope ,任务2就不会因为任务1的异常而被影响,取消了。
另外如果cancellation exception被捕获的话,任务也不会取消,会一直运行下去
1064

被折叠的 条评论
为什么被折叠?



