如何判断Kotlin泛型类型是否可为空?Retrofit映射问题求助
处理Retrofit Response映射Resource时201无响应体的问题
你编写的Retrofit Response转Resource的内联函数,在API返回201状态码且无响应体时会误判为Error,但这类场景(比如资源创建成功)属于正常业务成功情况,下面提供两种可行的修改方案:
方案一:基于状态码+泛型可空性适配
Retrofit的isSuccessful包含200-299所有成功状态码,但像201(创建成功)、204(无内容)这类状态码本身就允许无响应体。我们可以针对这类状态码做特殊处理,同时判断泛型是否支持空值:
inline fun <reified T> Response<T>.mapToResource(): Resource<T> { return if (isSuccessful) { val body = body() when { // 匹配HTTP标准中允许无响应体的成功状态码 code() in 201..204 -> { // 判断泛型T是否为可空类型,是的话返回带null的Success if (null is T) { @Suppress("UNCHECKED_CAST") Resource.Success(null as T) } else { // 泛型不可为空时,根据业务选择:要么提示无数据,要么返回默认值 Log.w("Resource", "API返回成功状态码(${code()})但无响应体,泛型不可为空") Resource.Error("操作成功但无返回数据") } } body != null -> Resource.Success(body) else -> { Log.e("Resource", "API返回成功但无可用数据") Resource.Error("API返回成功但无可用数据") } } } else { val errorMsg = message().takeIf { it.isNotEmpty() } ?: "请求失败,状态码:${code()}" Log.e("Resource", errorMsg) Resource.Error(errorMsg) } }
说明
- 优先匹配201-204区间的状态码,这类场景下无响应体是符合HTTP规范的
- 通过
null is T判断泛型是否支持空值,适配Resource<Unit?>或Resource<Void?>这类无数据返回的接口定义 - 若泛型不可为空但遇到无响应体的成功状态,可根据业务需求调整逻辑(比如返回默认值而非Error)
方案二:扩展Resource密封类,新增无数据成功类型
如果业务中频繁出现无数据的成功场景,建议给Resource新增一个语义明确的EmptySuccess类型,避免依赖泛型可空性:
首先调整Resource密封类定义:
sealed class Resource<out T> { data class Success<out T>(val data: T) : Resource<T>() object EmptySuccess : Resource<Nothing>() // 专门用于无数据的成功场景 data class Error(val message: String) : Resource<Nothing>() }
然后修改映射函数:
inline fun <reified T> Response<T>.mapToResource(): Resource<T> { return if (isSuccessful) { val body = body() when { code() in 201..204 -> Resource.EmptySuccess as Resource<T> body != null -> Resource.Success(body) else -> { Log.e("Resource", "API返回成功但无可用数据") Resource.Error("API返回成功但无可用数据") } } } else { val errorMsg = message().takeIf { it.isNotEmpty() } ?: "请求失败,状态码:${code()}" Log.e("Resource", errorMsg) Resource.Error(errorMsg) } }
说明
EmptySuccess明确标识“操作成功但无数据返回”的场景,调用方处理时可以清晰区分不同成功状态,避免null带来的潜在问题- 这种方式语义更清晰,适合业务中大量存在创建、删除等无需返回数据的接口场景
总结
- 若只是偶尔遇到201无响应体的情况,方案一足够灵活,不需要修改Resource类结构
- 若这类场景较多,方案二更优,通过明确的状态类型减少后续维护的歧义
内容的提问来源于stack exchange,提问作者AphonicLoqui
相关产品推荐
相关产品推荐

