首页 文章

Kotlin coroutine吞下例外

提问于
浏览
4

关于异常处理如何与协同程序一起使用,我感到非常困惑 .

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

我做了这个简单的例子来尝试协同程序但是如果我取消注释 throw 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

    当使用 async 时,你应该在某处获得结果,这样你就不会丢失任何异常 .

  • 2

    这是基于Alexey Romanov 's answer. With a bit more work I'捕获异常的代码 . 添加 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()
        }
    }
    

相关问题