Retrofit service contracts and error handling
interface OrdersApi {
@GET("v1/orders/{id}")
suspend fun order(@Path("id") id: String): OrderDto
@POST("v1/orders")
suspend fun place(
@Header("Idempotency-Key") key: String,
@Body request: PlaceOrderRequest,
): Response<PlaceOrderResponse>
}
Returning DTO directly throws HttpException for non-2xx and serialization/network exceptions. Response<T> exposes status/headers/error body for deliberate mapping but pushes protocol handling to caller. Choose one team convention and central adapter/mapping.
Suspend and cancellation
Retrofit suspend calls integrate cancellation with OkHttp call. Cancellation of client does not guarantee server stopped after bytes were sent. Mutation safety still requires idempotency/status recovery.
URL safety
@Pathis encoded path segment by default.@Queryhandles encoding; do not concatenate raw user input into URL.@Urlpermits dynamic URLs and is a security boundary—restrict scheme/host to prevent SSRF-style requests or token leakage.
Empty/nullable bodies
204 has no body. A 200 with malformed/missing body is a protocol failure, not automatically null. Model Response<Unit> for no content and explicit optional semantics where API promises them.
Error mapping
suspend fun <T> apiCall(block: suspend () -> T): DataResult<T> = try {
DataResult.Success(block())
} catch (e: CancellationException) {
throw e
} catch (e: HttpException) {
mapHttp(e)
} catch (e: IOException) {
DataResult.Failure(DataFailure.Network(e))
} catch (e: SerializationException) {
DataResult.Failure(DataFailure.Protocol(e))
}
Do not catch Throwable and erase programming errors/cancellation. Error-body parsing itself can fail and should be bounded/redacted.
Service design
Keep Retrofit DTO/protocol interface inside remote data source. Repository receives mapped application models/failures. Avoid passing Android Context or UI state into service.
Testing
Use MockWebServer to assert method/path/query/headers/body and simulate status, malformed JSON, disconnect, delay, chunked body, redirects, and cancellation. Mocking interface alone misses converters/interceptors/HTTP integration.
2xx can contain schema-invalid values. Validate mapping and business invariants before persistence/use.
Sources
Exercises
- Choose direct DTO versus Response for three endpoints.
- Handle 204 and malformed 200 correctly.
- Secure a dynamic
@Urlimage download.