文章目录
-
一、Android 协程中出现异常导致应用崩溃
-
二、Android 协程中使用协程异常处理器捕获异常
-
三、Android 全局异常处理器
一、Android 协程中出现异常导致应用崩溃
在前几篇博客示例中 , 协程中 如果出现异常 , 没有进行捕获 , 则程序直接崩溃 , 这种情况下需要进行 异常的捕获 以 避免 Android 应用程序的崩溃 ;
示例代码 :
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
GlobalScope.launch {
Log.i(TAG, "验证协程中抛出异常")
throw IllegalArgumentException()
}
}
}
执行结果 :
在协程中抛出了异常 , 应用直接退出 ;
15:46:00.444 I 验证协程中抛出异常
15:46:00.486 D Skia GL Pipeline
15:46:00.504 E FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: kim.hsl.coroutine, PID: 26587
java.lang.IllegalArgumentException
at kim.hsl.coroutine.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:18)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
15:46:00.511 W Force finishing activity kim.hsl.coroutine/.MainActivity
15:46:00.528 I Sending signal. PID: 26587 SIG: 9
---------------------------- PROCESS ENDED (26587) for package kim.hsl.coroutine ----------------------------
二、Android 协程中使用协程异常处理器捕获异常
在 Android 程序中 , 可以使用 协程异常处理器 CoroutineExceptionHandler 捕获异常 , 将其实例对象传递给 launch 协程构建器 作为参数即可 ;
该参数作为 协程上下文 的 协程异常处理器 CoroutineExceptionHandler 元素 ;
代码示例 :
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 创建 协程异常处理器 CoroutineExceptionHandler
val coroutineExceptionHandler = CoroutineExceptionHandler {
coroutineContext, throwable ->
Log.i(TAG, "CoroutineExceptionHandler 中处理异常 " +
"\n协程上下文 ${coroutineContext}" +
"\n异常内容 ${throwable}")
}
GlobalScope.launch {
Log.i(TAG, "验证协程中抛出异常")
throw IllegalArgumentException()
}
}
}
执行结果 :
协程异常处理器 CoroutineExceptionHandler 捕获到了异常 ;
15:47:54.749 I 验证协程中抛出异常
15:47:54.754 I CoroutineExceptionHandler 中处理异常
协程上下文 [kim.hsl.coroutine.MainActivity$onCreate$$inlined$CoroutineExceptionHandler$1@bc6a601, StandaloneCoroutine{Cancelling}@fef2ca6, Dispatchers.Default]
异常内容 java.lang.IllegalArgumentException
三、Android 全局异常处理器
Android 中的
全局异常处理器
, 可以 获取 所有的 协程 中产生的 没有被捕获的异常 ;
-
无法阻止崩溃 :
全局异常处理器 不能捕获这些异常 进行处理 , 应用程序 还是要崩溃 ;
-
用于调试上报 :
全局异常处理器 仅用于 程序调试 和 异常上报 场景
全局异常处理器使用步骤如下 :
① 在 app/main/ 目录下创建 resources 目录 , 在 resources 目录下创建 META-INF
② 在 META-INF 目录下创建 services
③ 在 app/main/resources/META-INF/services 目录下 , 创建 名称为 kotlinx.coroutines.CoroutineExceptionHandler
④ 创建 协程的 全局异常处理器 MyCoroutineExceptionHandler 自定义类 , 需要 实现 CoroutineExceptionHandler 接口 ; 并覆盖接口中的
val key
成员变量 和
fun handleException(context: CoroutineContext, exception: Throwable)
成员方法 ;
package kim.hsl.coroutine
import android.util.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlin.coroutines.CoroutineContext
class MyCoroutineExceptionHandler : CoroutineExceptionHandler {
val TAG = "MyCoroutineExceptionHandler"
override val key = CoroutineExceptionHandler
override fun handleException(context: CoroutineContext, exception: Throwable) {
Log.i(TAG, "在 MyCoroutineExceptionHandler 全局异常处理器 中处理未捕获异常 " +
"\n协程上下文 ${context}" +
"\n抛出异常 ${exception}")
}
}
⑤ 在 app/main/resources/META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler 文件中配置 协程的 全局异常处理器 MyCoroutineExceptionHandler 自定义类 的全类名
kim.hsl.coroutine.MyCoroutineExceptionHandler
, 如下图所示 :
⑥ 在 Activity 中实现一个 抛出异常的协程 :
package kim.hsl.coroutine
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
GlobalScope.launch() {
Log.i(TAG, "验证协程中抛出异常")
throw IllegalArgumentException()
}
}
}
⑦ 执行上述应用 , 会抛出异常 , 协程中也不进行异常处理 , 此时执行结果如下 :
16:30:53.537 I 验证协程中抛出异常
16:30:53.578 D Skia GL Pipeline
16:30:53.590 I 在 MyCoroutineExceptionHandler 全局异常处理器 中处理未捕获异常
协程上下文 [StandaloneCoroutine{Cancelling}@8252a7e, Dispatchers.Default]
抛出异常 java.lang.IllegalArgumentException
16:30:53.593 E FATAL EXCEPTION: DefaultDispatcher-worker-1
Process: kim.hsl.coroutine, PID: 8808
java.lang.IllegalArgumentException
at kim.hsl.coroutine.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:18)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
16:30:53.599 W Force finishing activity kim.hsl.coroutine/.MainActivity
16:30:53.608 I Sending signal. PID: 8808 SIG: 9
16:30:53.627 I Process kim.hsl.coroutine (pid 8808) has died: cch CRE
---------------------------- PROCESS ENDED (8808) for package kim.hsl.coroutine ----------------------------
在 MyCoroutineExceptionHandler 全局异常处理器 中处理未捕获异常 , 但是程序依然崩溃 , 可以在 全局异常处理器 中获取到异常信息 ;