Special Cases
Handling empty response bodies
Some operations rely solely on the returned response code. In such cases, the body is usually empty. Use Unit
as the response type for such APIs:
suspend fun updateStatusOnServer(): NetworkResponse<Unit, ErrorType>
If your server sometimes returns a body and sometimes doesn't (200 vs 204 status code), then consider using the bundled raw Retrofit response.
interface PostsService {
@GET("/")
suspend fun getPost(): NetworkResponse<Unit, ErrorResponse>
}
when (val postResponse = service.getPost()) {
is NetworkResponse.Success -> {
if (postResponse.code != 204) {
val rawBody = postResponse.response.rawBody()
// Manually parse the raw body to access the response
}
}
is NetworkResponse.Error -> { ... }
}
Handling primitive responses
The most common format for sending data over the wire is JSON. However, not all responses need JSON objects as sometimes primitive string suffice. To support a wide variety of response types, Retrofit supports adding custom converters. One such converter is the Scalars Converter which can handle primitive response types.
To use it, use a primitive as your response type:
interface Api {
@GET("/details")
suspend fun details(): NetworkResponse<String, String>
}
And then make sure that the Scalars converter is added to Retrofit before the JSON converter:
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(NetworkResponseAdapterFactory())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(moshi))
.baseUrl("...")
.build()
Raw Retrofit Responses
Responses of type NetworkResponse.Success
, NetworkResponse.ServerError
and NetworkResponse.UnknownError
are bundled with the raw Retrofit Response
object (if available). This allows you to interact with raw response in case you ever need it:
when (networkResponse) {
is NetworkResponse.Success -> {
val statusCode = networkResponse.response.code()
}
}