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()内部,说明异常是从回调逻辑中流出的。
正确处理方式
确保
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) { // 处理响应逻辑 } })全局捕获线程池未捕获异常(可选)
如果你无法确保所有回调都不会抛出异常,可以给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()排查自定义Interceptor是否存在异常泄漏
检查你的DeviceInterceptor实现,确保intercept方法中所有异常都被正确处理或传递,不会出现未捕获的Throwable(不过从堆栈看,异常是在DNS解析阶段抛出,Interceptor只是执行链路中的一环,大概率不是这里的问题)。
内容的提问来源于stack exchange,提问作者DIG

