асинхронная обработка исключений kotlin - PullRequest
0 голосов
/ 14 ноября 2018

Учитывая следующий фрагмент, я не понимаю, почему мое приложение для 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$1$res$1.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, выполнение достигает "основного конца" 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: Я добавил трассировку стека аварийного отказа.

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Вы можете найти свой ответ здесь: https://proandroiddev.com/kotlin-coroutines-patterns-anti-patterns-f9d12984c68e

Подводя итог, существует несколько способов отловить исключения с помощью async.

1 - Wrap async вызов с supervisorScope

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 - упаковка async с coroutineScope

launch {
    try {
        coroutineScope {
            val task = async {
                methodThatThrowsException()
            }
            updateUI("Ok ${task.await()}")
        }
    } catch (e: Throwable) {
        showError("Erro! ${e.message}")
    }
}
0 голосов
/ 14 ноября 2018

Во втором примере, если вы добавите Thread.sleep(1000) после вашего оператора println("main end"), вы также увидите исключение.Без sleep приложение завершается до выдачи исключения:

Exception in thread "DefaultDispatcher-worker-3" java.lang.Exception: aaa
at de.e2.app$Companion$main$job$1$1.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 выдается исключение, собственная сопрограмма отменяется, а также родительские сопрограммы: см. Подпрограмма Kotlin не может обработать исключение

...