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
相关产品推荐
相关产品推荐

