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: CoroutineScopeget() {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被捕获的话,任务也不会取消,会一直运行下去