I've following class to map request status (Loading, Success, Error)
data class Resource<out T>(
val status: Status,
val data: T?
) {
sealed class Status {
data class Success<out T>(val data: T?) : Status()
data class Error(
val message: String,
val statusCode: Int
) : Status()
object Loading : Status()
}
companion object {
fun <T> success(data: T?): Resource<T> {
return Resource(status = Status.Success(data), data = data)
}
fun <T> error(msg: String, statusCode: Int, data: T? = null): Resource<T> {
return Resource(status = Status.Error(msg, statusCode), data = data)
}
fun <T> loading(data: T? = null): Resource<T> {
return Resource(status = Status.Loading, data = data)
}
}
}
I use following class to map the request
inline fun <REMOTE> networkResource(
crossinline fetchFromRemote: suspend () -> Flow<ApiResponse<REMOTE>>,
crossinline onFetchFailed: (errorBody: String?, statusCode: Int) -> Unit = { _: String?, _: Int -> }
) = flow<Resource<REMOTE>> {
emit(Resource.loading(null))
fetchFromRemote().collect { apiResponse ->
when (apiResponse) {
is ApiSuccessResponse -> {
apiResponse.body?.let {
emit(Resource.success(data = it))
}
}
is ApiErrorResponse -> {
onFetchFailed(apiResponse.errorMessage, apiResponse.statusCode)
emit(Resource.error(msg = apiResponse.errorMessage, statusCode = apiResponse.statusCode, data = null))
}
is ApiEmptyResponse -> {
emit(Resource.success(data = null))
}
}
}
}
I use that class as below
fun getSomething(): Flow<Resource<SuccessResponse<GetCartResponse>>> {
return networkResource(
fetchFromRemote = { cartApi.getCart() },
onFetchFailed = { _, _ -> }
).flowOn(Dispatchers.IO)
}
When i try to map that flow, I'm seeing unchecked cast issue. I've tried to play with reified type but found no solution.
getSomething().collect { response ->
when (response.status) {
is Resource.Status.Loading -> {
Resource.loading(null)
}
is Resource.Status.Success<*> -> {
// Below line states that Unchecked cast: Resource.Status to Resource.Status.Success<Quote>
val quote = it.status as Resource.Status.Success<Quote>
Resource.success(quote.data)
}
is Resource.Status.Error -> {
val error = it.status as Resource.Status.Error
Resource.error(error.message, error.statusCode)
}
}
}
How should i make sure that i have access to type T correctly? For more details, please see this