You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OkHttp4中try-catch无法捕获UnknownHostException问题问询

问题分析与解决方案

为什么异常未被OkHttp捕获?

核心原因是你的请求回调onFailure方法中重新抛出了异常,而非OkHttp的try-catch逻辑失效。

查看OkHttp 4.10.0的AsyncCall.run()源码:当getResponseWithInterceptorChain()抛出UnknownHostException(属于IOException子类)时,会被第一个catch (e: IOException)分支捕获,随后调用responseCallback.onFailure()。如果你的onFailure实现中直接抛出了接收到的异常(或其他异常),这个异常会逃出当前的catch块,触发第二个catch (t: Throwable)分支——而这个分支最后会执行throw t,将异常抛给线程池,最终成为未捕获异常被Crashlytics捕获。

你的崩溃堆栈也印证了这一点:异常的传播终点是RealCall$AsyncCall.run(),而非getResponseWithInterceptorChain()内部,说明异常是从回调逻辑中流出的。

正确处理方式

  1. 确保onFailure回调内部不抛出异常
    所有异常处理逻辑都应在回调内部完成,比如仅记录日志、更新UI状态,不要将异常重新抛出:

    call.enqueue(object : Callback {
        override fun onFailure(call: Call, e: IOException) {
            // 仅记录日志,不抛出异常
            Log.e("API_ERROR", "请求失败: ${e.message}", e)
            // 处理UI状态更新等逻辑
        }
    
        override fun onResponse(call: Call, response: Response) {
            // 处理响应逻辑
        }
    })
    
  2. 全局捕获线程池未捕获异常(可选)
    如果你无法确保所有回调都不会抛出异常,可以给OkHttp的线程池设置未捕获异常处理器,避免异常扩散到Crashlytics:

    val okHttpClient = OkHttpClient.Builder()
        .dispatcher(Dispatcher().apply {
            executorService = Executors.newCachedThreadPool { runnable ->
                Thread(runnable).apply {
                    uncaughtExceptionHandler = Thread.UncaughtExceptionHandler { _, throwable ->
                        Log.e("OKHTTP_UNCAUGHT", "线程未捕获异常", throwable)
                    }
                }
            }
        })
        .build()
    
  3. 排查自定义Interceptor是否存在异常泄漏
    检查你的DeviceInterceptor实现,确保intercept方法中所有异常都被正确处理或传递,不会出现未捕获的Throwable(不过从堆栈看,异常是在DNS解析阶段抛出,Interceptor只是执行链路中的一环,大概率不是这里的问题)。

内容的提问来源于stack exchange,提问作者DIG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 13:30:24