Kotlin coroutine吞下例外

时间:2017-12-12 23:19:37

标签: android exception kotlin kotlinx.coroutines

我对异常处理如何与协同程序一起工作非常困惑。

我希望有可能有一系列挂起函数可以像同步代码一样在它们之间传递Exceptions。因此,如果说Retrofit抛出IOException,我可以在挂起函数链的开头处理该异常,例如在演示者中向用户显示错误。

我做了这个简单的例子来尝试协同程序但是如果我取消注释throw Exception在Exception无法运行之后调用代码但是Exception不会使应用程序崩溃。

package com.example.myapplication

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Button
import android.widget.TextView
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val text = findViewById<TextView>(R.id.thing_text)
        val button = findViewById<Button>(R.id.thing_button)

        var count = 0

        button.setOnClickListener {
            launch {
                count++
//                throw Exception("Boom")
                val string = delayedStringOfInt(count)
                runOnUiThread { text.text = string }
            }
        }
    }

    suspend fun delayedStringOfInt(int: Int): String {
        delay(1000)
//        throw Exception("Boom")
        return int.toString()
    }
}

我尝试过使用asyncCoroutineExceptionHandler

2 个答案:

答案 0 :(得分:2)

使用async时,您应该await某个地方的结果,这样您就不会失去任何例外。

答案 1 :(得分:1)

以下是根据Alexey Romanov的回答捕获异常的代码。通过更多的工作,我已经开始使用它了。添加Log.d("thread", Thread.currentThread().name)表示延迟不会阻止UI。

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val text = findViewById<TextView>(R.id.thing_text)
        val button = findViewById<Button>(R.id.thing_button)

        var count = 0

        button.setOnClickListener {
            launch {
                val job = async {
                    count++

                    val string = delayedStringOfInt(count)
                    updateTextView(text, string)
                }

                try {
                    job.await()
                } catch (e: IOException) {
                    makeToastFromException(e)
                }
            }
        }
    }

    fun makeToastFromException(e: Exception) {
        runOnUiThread {
            Toast.makeText(this@MainActivity, e.localizedMessage, Toast.LENGTH_SHORT).show()
        }
    }

    fun updateTextView(text: TextView, string: String) {
        runOnUiThread { text.text = string }
    }

    suspend fun delayedStringOfInt(int: Int): String {
        delay(2000)
        if (int % 4 == 0) throw IOException("Boom")
        return int.toString()
    }
}