kotlin 异步异常处理
kotlin async exception handling
鉴于以下代码段,我不明白为什么我的 android 应用会崩溃。我在独立的 kotlin 应用程序中进行了测试,但这并没有发生。
class LoginActivity : AppCompatActivity(), CoroutineScope
{
lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
job = Job()
try
{
launch()
{
try
{
var res = async { test() }
res.await()
}
catch (e2: java.lang.Exception)
{
}
}
}
catch (e: java.lang.Exception)
{
}
}
fun test(): String
{
throw java.lang.Exception("test ex")
return "";
}
}
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ro.ingr.ingeeasafety, PID: 11298
java.lang.Exception: test ex
at ro.ingr.ingeeasafety.activities.LoginActivity.test(LoginActivity.kt:72)
at ro.ingr.ingeeasafety.activities.LoginActivity$onCreate$res.invokeSuspend(LoginActivity.kt:48)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
独立的kotlin应用程序代码,执行达到"main end" println
class app
{
companion object :CoroutineScope
{
lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Default+ job
init
{
job=Job()
}
@JvmStatic
fun main(args: Array<String>)
{
launch()
{
try
{
async()
{
println("async start")
throw Exception("aaa")
}.await()
}
catch (e: Exception)
{
println("async exception")
}
}
println("main end")
}
}
}
我正在尝试创建一个流程,我从某个地方加载一些东西,如果加载操作失败,我的应用程序不会崩溃。我原以为异常会在定义的处理程序中被捕获。
LE:我添加了崩溃堆栈跟踪。
在您的第二个示例中,如果您在 println("main end")
语句之后添加 Thread.sleep(1000)
,您也会看到异常。没有 sleep
应用程序在抛出异常之前结束:
Exception in thread "DefaultDispatcher-worker-3" java.lang.Exception: aaa
at de.e2.app$Companion$main$job.invokeSuspend(AsyncProblem2.kt:26)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
在这两种情况下,您 运行 进入 Kotlin 1.3 引入的结构化并发的标准行为(参见 https://medium.com/@elizarov/structured-concurrency-722d765aa952)。
如果在 async
块中抛出异常,则取消自己的协程以及父协程:参见
您可以在这里找到答案:
https://proandroiddev.com/kotlin-coroutines-patterns-anti-patterns-f9d12984c68e
总而言之,有几种方法可以使用 async
捕获异常。
1 - 用 supervisorScope
包装 async
调用
launch {
supervisorScope {
val task = async {
methodThatThrowsException()
}
try {
updateUI("Ok ${task.await()}")
} catch (e: Throwable) {
showError("Erro! ${e.message}")
}
}
}
2 - 传递一个 SupervisorJob
作为参数
launch {
// parentJob (optional) is the parent Job of the CoroutineContext
val task = async(SupervisorJob(parentJob)) {
methodThatThrowsException()
}
try {
updateUI("Ok ${task.await()}")
} catch (e: Throwable) {
showError("Erro! ${e.message}")
}
}
3 - 用 coroutineScope
包装 async
launch {
try {
coroutineScope {
val task = async {
methodThatThrowsException()
}
updateUI("Ok ${task.await()}")
}
} catch (e: Throwable) {
showError("Erro! ${e.message}")
}
}
鉴于以下代码段,我不明白为什么我的 android 应用会崩溃。我在独立的 kotlin 应用程序中进行了测试,但这并没有发生。
class LoginActivity : AppCompatActivity(), CoroutineScope
{
lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
job = Job()
try
{
launch()
{
try
{
var res = async { test() }
res.await()
}
catch (e2: java.lang.Exception)
{
}
}
}
catch (e: java.lang.Exception)
{
}
}
fun test(): String
{
throw java.lang.Exception("test ex")
return "";
}
}
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ro.ingr.ingeeasafety, PID: 11298
java.lang.Exception: test ex
at ro.ingr.ingeeasafety.activities.LoginActivity.test(LoginActivity.kt:72)
at ro.ingr.ingeeasafety.activities.LoginActivity$onCreate$res.invokeSuspend(LoginActivity.kt:48)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
独立的kotlin应用程序代码,执行达到"main end" println
class app
{
companion object :CoroutineScope
{
lateinit var job: Job
override val coroutineContext: CoroutineContext
get() = Dispatchers.Default+ job
init
{
job=Job()
}
@JvmStatic
fun main(args: Array<String>)
{
launch()
{
try
{
async()
{
println("async start")
throw Exception("aaa")
}.await()
}
catch (e: Exception)
{
println("async exception")
}
}
println("main end")
}
}
}
我正在尝试创建一个流程,我从某个地方加载一些东西,如果加载操作失败,我的应用程序不会崩溃。我原以为异常会在定义的处理程序中被捕获。
LE:我添加了崩溃堆栈跟踪。
在您的第二个示例中,如果您在 println("main end")
语句之后添加 Thread.sleep(1000)
,您也会看到异常。没有 sleep
应用程序在抛出异常之前结束:
Exception in thread "DefaultDispatcher-worker-3" java.lang.Exception: aaa
at de.e2.app$Companion$main$job.invokeSuspend(AsyncProblem2.kt:26)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:236)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
在这两种情况下,您 运行 进入 Kotlin 1.3 引入的结构化并发的标准行为(参见 https://medium.com/@elizarov/structured-concurrency-722d765aa952)。
如果在 async
块中抛出异常,则取消自己的协程以及父协程:参见
您可以在这里找到答案: https://proandroiddev.com/kotlin-coroutines-patterns-anti-patterns-f9d12984c68e
总而言之,有几种方法可以使用 async
捕获异常。
1 - 用 supervisorScope
包装 async
调用
launch {
supervisorScope {
val task = async {
methodThatThrowsException()
}
try {
updateUI("Ok ${task.await()}")
} catch (e: Throwable) {
showError("Erro! ${e.message}")
}
}
}
2 - 传递一个 SupervisorJob
作为参数
launch {
// parentJob (optional) is the parent Job of the CoroutineContext
val task = async(SupervisorJob(parentJob)) {
methodThatThrowsException()
}
try {
updateUI("Ok ${task.await()}")
} catch (e: Throwable) {
showError("Erro! ${e.message}")
}
}
3 - 用 coroutineScope
包装 async
launch {
try {
coroutineScope {
val task = async {
methodThatThrowsException()
}
updateUI("Ok ${task.await()}")
}
} catch (e: Throwable) {
showError("Erro! ${e.message}")
}
}