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

Retrofit协程调用始终抛出kotlin.Unit异常,如何获取Java异常?

解决Retrofit协程调用时捕获到kotlin.Unit异常的问题

问题根源

你当前的ApiService定义为普通类,不符合Retrofit的使用规范。Retrofit要求API接口必须是接口类型,由Retrofit通过动态代理生成实现类,才能正确处理网络请求的异常抛出。如果自行定义普通类的suspend函数,Retrofit无法注入网络请求逻辑,异常会被错误处理,最终导致捕获到无意义的kotlin.Unit异常。

解决方案

1. 修正ApiService为接口

将ApiService改为接口,同时为每个方法添加对应的HTTP注解(根据实际接口路径调整):

interface ApiService {
    @GET("data")
    suspend fun getData(): Data

    @GET("user")
    suspend fun getUser(): User
}

2. 正确初始化Retrofit并生成ApiService实例

必须通过Retrofit的create方法生成ApiService的实现类,不能自行实例化:

val retrofit = Retrofit.Builder()
    .baseUrl("你的API基础地址")
    .addConverterFactory(GsonConverterFactory.create()) // 根据序列化需求选择对应转换器
    .build()

val apiService = retrofit.create(ApiService::class.java)

3. 确保ViewModel使用正确的ApiService实例

ViewModel中注入的service必须是上述Retrofit生成的实例,而非自定义类的对象:

class UserViewModel(private val service: ApiService) : ViewModel() {
    private val TAG = "UserViewModel"

    fun fetchUser() = viewModelScope.launch(Dispatchers.IO) {
        try {
            val user = service.getUser()
            // 处理成功返回的数据
        } catch (e: Exception) {
            Log.d(TAG, "获取用户失败: ${e.javaClass.simpleName} - ${e.message}")
            // 此时可捕获到实际异常,比如UnknownHostException、IOException等
        }
    }
}

4. 自定义拦截器的异常处理规范

如果使用自定义拦截器,禁止吞掉异常,必须将异常重新抛出供上层捕获:

class CustomInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        return try {
            chain.proceed(chain.request())
        } catch (e: IOException) {
            Log.e("Interceptor", "网络请求异常: ${e.message}")
            throw e // 必须重新抛出,不能中断异常传递链
        }
    }
}

验证

完成上述修改后,当出现网络断开、接口报错等问题时,ViewModel的catch块就能捕获到对应的实际异常,从而明确错误的根本原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:23:23