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

Android中Retrofit2请求SocketTimeoutException崩溃问题求助

Retrofit2 捕获SocketTimeoutException并避免崩溃的解决方案

崩溃的核心原因是未在请求流程中捕获SocketTimeoutException(属于IOException子类),导致未处理异常直接抛出引发崩溃。以下是针对不同请求方式的具体处理方案:

1. 协程(Coroutines)请求场景

如果使用ViewModel+协程架构,直接在请求代码块外层包裹try-catch,单独捕获超时异常:

viewModelScope.launch {
    try {
        val response = apiService.getData()
        if (response.isSuccessful) {
            // 处理接口返回的有效数据
        } else {
            // 处理HTTP错误码(如404、500等)
        }
    } catch (e: SocketTimeoutException) {
        // 显示超时提示
        Toast.makeText(context, "连接超时", Toast.LENGTH_SHORT).show()
    } catch (e: IOException) {
        // 处理其他网络IO异常(如连接失败、DNS解析失败等)
        Toast.makeText(context, "网络异常,请稍后重试", Toast.LENGTH_SHORT).show()
    } catch (e: Exception) {
        // 兜底处理其他未知异常
        Toast.makeText(context, "请求失败,请稍后重试", Toast.LENGTH_SHORT).show()
    }
}

2. Retrofit Call异步回调场景

使用传统enqueue异步请求时,在onFailure回调中判断异常类型:

apiService.getData().enqueue(object : Callback<DataModel> {
    override fun onResponse(call: Call<DataModel>, response: Response<DataModel>) {
        if (response.isSuccessful) {
            // 处理成功响应
        } else {
            // 处理HTTP错误
        }
    }

    override fun onFailure(call: Call<DataModel>, t: Throwable) {
        when (t) {
            is SocketTimeoutException -> Toast.makeText(context, "连接超时", Toast.LENGTH_SHORT).show()
            is IOException -> Toast.makeText(context, "网络异常,请稍后重试", Toast.LENGTH_SHORT).show()
            else -> Toast.makeText(context, "请求失败,请稍后重试", Toast.LENGTH_SHORT).show()
        }
    }
})

3. 全局统一异常处理(可选)

如果想避免重复编写异常捕获代码,可以在BaseViewModel中封装全局异常处理器:

open class BaseViewModel : ViewModel() {
    private val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
        handleException(throwable)
    }

    private fun handleException(throwable: Throwable) {
        val message = when (throwable) {
            is SocketTimeoutException -> "连接超时"
            is IOException -> "网络异常,请稍后重试"
            else -> "请求失败,请稍后重试"
        }
        // 这里可以通过LiveData通知UI层显示提示
        _toastMessage.postValue(message)
    }

    protected fun launchSafe(block: suspend () -> Unit) {
        viewModelScope.launch(exceptionHandler) {
            block()
        }
    }
}

子ViewModel直接调用封装好的launchSafe发起请求即可:

class MyViewModel : BaseViewModel() {
    fun fetchData() {
        launchSafe {
            val response = apiService.getData()
            // 处理响应数据
        }
    }
}

关键注意点

  • 确保所有网络请求的异常都被捕获,不要让异常直接抛到主线程未捕获异常的层级;
  • SocketTimeoutException是IOException的子类,所以需要单独捕获才能区分超时场景和其他网络异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:18:34