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

