I have an app where I make an API call with RetroFit and the API response will have a standard format with the actual result in an object in the JSON. Every API call is wrapped in this object:
data class EventResponse<T>(
val event: EventObject,
val data: T?,
)
data class EventObject(
val error: Boolean = false,
val success: Boolean = false,
val message: String? = null,
)
The JSON looks like this:
{
"event": {
"success": true,
"error": false,
"message": "Some message",
},
"data": {"someJsonObject":"someValue"},
}
Currently, the app doesn't handle it too well when the data is null. I've tried changing my code to allow nullable objects but then I get a type mismatch error where I call the function and the objects are non-nullable.
For example, take 2 example API calls. 1 returns a list wrapped in the EventResponse, and another just a single object
fun getUser(@Query("user_id") id: String): Single<EventResponse<List<UserRemoteModel>>>
fun getSuperUser(): Single<EventResponse<SuperUserRemoteModel>>
These are called as follows:
ApiCallWrapper.makeCall(api.getUser(userId))
My ApiCallWrapper code is as follows:
object ApiCallWrapper {
var eventHandler: ((event: EventObject) -> Unit)? = null
fun <T : Any?> makeCall(apiCall: Single<EventResponse<T?>>): Single<T?> {
return apiCall.handleResponse(eventHandler)
}
}
fun <T : Any?> Single<EventResponse<T?>>.handleResponse(eventHandler: ((event: EventObject) -> Unit)?): Single<T?> {
return this
.onErrorReturn {
it.printStackTrace()
EventResponse.default(error = true, success = false, show = true, message = it.localizedMessage)
}
.doOnError { it.printStackTrace() }
.flatMap { response ->
eventHandler?.invoke(response.event)
if (!response.event.success || response.event.error) {
throw Exception(response.event.message ?: "Unknown error")
} else {
Single.just(response.data) // <--- SOURCE OF ERROR
}
}
}
So when the data is not null, this all works fine. However, I've changed the API calls that could possible be nullable to the following:
fun getUser(@Query("user_id") id: String): Single<EventResponse<List<UserRemoteModel>?>>
So I'm trying to say that the EventResponse won't be null but the object (List or normal object) can be null.
When I make this change to make it nullable, I get an error on all other calls that are NOT nullable:
Type mismatch.
Required:
Single<EventResponse<TypeVariable(T)?>>
Found:
Single<EventResponse<NonNullRemoteModel>>
So its telling me there's a Type Mismatch because it's looking for T? and I'm passing T.
This started happening after I changed my ApiCAllWrapper method signature:
- fun <T : Any?> makeCall(apiCall: Single<EventResponse<T>>): Single<T?> {
+ fun <T : Any?> makeCall(apiCall: Single<EventResponse<T?>>): Single<T?> {
and
-fun <T : Any?> Single<EventResponse<T>>.handleResponse(eventHandler: ((event: EventObject) -> Unit)?): Single<T?> {
+fun <T : Any?> Single<EventResponse<T?>>.handleResponse(eventHandler: ((event: EventObject) -> Unit)?): Single<T?> {
It's a bit complicated to put it all in one post but the main issue is that I get an RxJava error when the data is null and it can stop further API calls, as I am calling all my different endpoints in an initial sync when I log in to the app, so I need to be able to handle this gracefully.
The other option is I find another way to handle my API responses that can support the generic Event format.
Thanks