返回类型与错误¶
同一个 Contract 可以按业务边界选择四种返回类型。
返回类型¶
| 声明 | 行为 | 推荐场景 |
|---|---|---|
NetworkCall<T> |
延迟执行,可继续组合策略 | 默认选择,Repository/UseCase |
suspend NetworkResult<T> |
立即执行,显式成功/失败 | 简单的一次性调用 |
Flow<NetworkState<T>> |
冷流,Loading → Success/Error | UI 直接收集 |
suspend T |
失败抛 NetworkRequestException |
已统一使用异常式调用的代码 |
@NetworkService
interface ResultApi {
@GET("/call") fun call(): NetworkCall<ItemDto>
@GET("/result") suspend fun result(): NetworkResult<ItemDto>
@GET("/state") fun state(): Flow<NetworkState<ItemDto>>
@GET("/data") suspend fun data(): ItemDto
}
NetworkResult¶
sealed interface NetworkResult<out T> {
data class Success<T>(
val data: T,
val statusCode: Int,
val headers: Map<String, String>,
val requestId: String,
val durationMillis: Long,
val attempt: Int,
val source: NetworkResponseSource,
) : NetworkResult<T>
data class Failure(val error: NetworkFailure) : NetworkResult<Nothing>
}
source 用来区分 NETWORK、MEMORY_CACHE、STALE_CACHE 和 LOCAL_FALLBACK。这比根据耗时或 Header
猜测数据来源稳定得多。
NetworkFailure¶
data class NetworkFailure(
val code: String,
val category: NetworkFailureCategory,
val message: String,
val statusCode: Int?,
val retryable: Boolean,
val requestId: String,
val attempt: Int,
val retryAfterMillis: Long,
)
分类包括:
| Category | 含义 | 常见处理 |
|---|---|---|
VALIDATION |
URL、业务数据或参数不合法 | 修复调用/提示业务错误,不重试 |
SERIALIZATION |
编解码失败 | 上报协议不兼容,不盲目重试 |
CONNECTIVITY / DNS |
离线或域名解析失败 | 等网络恢复,可使用缓存 |
TLS |
HTTPS/证书校验失败 | 阻断请求并上报,不能降级 HTTP |
TIMEOUT |
请求超时 | 幂等请求可有限重试 |
CANCELLED |
协程或页面主动取消 | 不提示为业务错误 |
CIRCUIT_OPEN |
熔断器拒绝 | 尊重 retryAfterMillis |
CLIENT_THROTTLED |
并发、队列或限流拒绝 | 降低调用频率 |
HTTP |
服务端非成功状态 | 结合 statusCode 与业务 code |
RESPONSE_TOO_LARGE |
超过响应体上限 | 改流式接口或提高明确上限 |
稳定分支¶
when (val result = api.detail(id).await()) {
is NetworkResult.Success -> save(result.data)
is NetworkResult.Failure -> when (result.error.category) {
NetworkFailureCategory.CANCELLED -> Unit
NetworkFailureCategory.CONNECTIVITY -> showOfflineCache()
NetworkFailureCategory.HTTP -> showServerError(result.error.statusCode)
else -> showGenericError(result.error.code)
}
}
不要匹配平台异常类名或 message 文本;它们不是跨端稳定 Contract。
自定义错误映射¶
平台响应先由 NetworkResponseAdapter 解开统一业务外壳,再由 NetworkErrorMapper 把普通 HTTP 失败映射为
结构化错误。具体示例见Converter 与响应外壳。