【问题标题】:Kotlin Exception not caught?Kotlin 异常没有被捕获?
【发布时间】:2021-03-01 13:49:19
【问题描述】:

我想知道为什么使用以下代码没有捕获异常:

private inline fun <reified T : Any> parseResponse(
        httpConnection: HttpURLConnection,
        noinline callback: ResponseBlock<T>?
    ) {
        with(httpConnection) {
            var error: Throwable? = null
            val model = try {
                if (this.responseCode in 200..299) {
                    jacksonObjectMapper().readValue(
                        this.inputStream.bufferedReader().readText(),
                        T::class.java
                    )
                } else {
                    null
                }
            } catch (e: Exception) {
                error = e
                null
            }

            if (model == null && error == null) {
                error = try {
                    if (this.responseCode !in 200..299) {
                        val errorResponse = this.errorStream.bufferedReader().readText()
                        Throwable(errorResponse)
                    } else {
                        null
                    }
                } catch (e: Exception) {
                    e
                }
            }
            error?.let {
                Log.e(this::class.simpleName, it.message, it)
            }
            callback?.invoke(this.responseCode, model, error)
            this.disconnect()
        }
    }

函数被这样调用:

private inline fun <reified T : Any> get(
        pathComponents: Array<String>,
        noinline callback: ResponseBlock<T>?,
        queryParameters: Map<String, Any>? = null
    ) {
        thread(start = true) {
            val urlRequest = createUrlRequest(HttpMethod.GET, pathComponents, queryParameters)
            parseResponse(urlRequest, callback)
        }
    }

我仍然得到这个导致应用程序崩溃的异常:

E/HttpURLConnectionImpl: Failed to connect to /10.0.2.2:8080
    java.net.ConnectException: Failed to connect to /10.0.2.2:8080
        at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:147)
        at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542)
        at io.openremote.app.network.ApiManager$getAppConfig$$inlined$get$1.invoke(ApiManager.kt:148)
        at io.openremote.app.network.ApiManager$getAppConfig$$inlined$get$1.invoke(ApiManager.kt:14)
        at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)
E/AndroidRuntime: FATAL EXCEPTION: Thread-2
    Process: io.openremote.app, PID: 3901
    java.net.ConnectException: Failed to connect to /10.0.2.2:8080
        at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:147)
        at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116)
        at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186)
        at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
        at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
        at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
        at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
        at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:542)
        at io.openremote.app.network.ApiManager$getAppConfig$$inlined$get$1.invoke(ApiManager.kt:148)
        at io.openremote.app.network.ApiManager$getAppConfig$$inlined$get$1.invoke(ApiManager.kt:14)
        at kotlin.concurrent.ThreadsKt$thread$thread$1.run(Thread.kt:30)

我会说 try/catch 块会捕获异常,但是唉...

是什么导致异常没有被捕获?我会说线程无关紧要,因为我使用 try/catch 块来处理线程中的异常。

更新

在 Laalto 的回答之后,我将代码更新为如下所示(对于那些感兴趣的人):

private inline fun <reified T : Any> parseResponse(
        httpConnection: HttpURLConnection,
        noinline callback: ResponseBlock<T>?
    ) {
        with(httpConnection) {
            val parsedResult = try {
                if (this.responseCode in 200..299) {
                    Triple(
                        this.responseCode, jacksonObjectMapper().readValue(
                            this.inputStream.bufferedReader().readText(),
                            T::class.java
                        ), null
                    )
                } else {
                    val errorResponse = this.errorStream.bufferedReader().readText()
                    Triple(this.responseCode, null, Throwable(errorResponse))
                }
            } catch (e: Exception) {
                Triple(0, null, e)
            }

            parsedResult.third?.let {
                Log.e(this::class.simpleName, it.message, it)
            }
            callback?.invoke(parsedResult.first, parsedResult.second, parsedResult.third)
            this.disconnect()
        }
    }

【问题讨论】:

  • 最后,您无需尝试捕获即可访问responseCode:callback?.invoke(this.responseCode, model, error)
  • 你是对的拉阿尔托。如果您将其添加为答案,我将接受它作为正确答案。

标签: android kotlin asynchronous


【解决方案1】:

堆栈跟踪显示尝试调用 getResponseCode() 的异常。在末尾没有 try-catch 块的情况下,只有一次访问 responseCode:

callback?.invoke(this.responseCode, model, error)

早期的 catch 块工作正常,但代码继续执行这部分,然后引发异常。

在您更新的问题中,您已经围绕此问题重新构建了代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 2013-08-08
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多