I am using flow{}
builder to call the api and then emit()
the response to ViewModel
. I add return type of flow as Flow<Resource<List<RemoteData>>>
. However, at some places in emit(), the Android Studio throws
error : Not enough information to infer type variable T
Because the emit(Resource.Error(message = "Couldn't reach server, check your internet connection."))
is expecting values of type List<RemoteData>
Please see my Resource
class below
sealed class Resource<T>(val data: T? = null, val message: String? = null) {
class Loading<T>(data: T? = null): Resource<T>(data)
class Success<T>(data: T?): Resource<T>(data)
class Error<T>(message: String, data: T? = null): Resource<T>(data, message)
}
My question, Is it safe to change emit to
emit(Resource.Error(
message = "Couldn't reach server, check your internet connection.",
data = null
))
And flow's return type as Flow<Resource<out List<RemoteData>>>
?
CodePudding user response:
Kotlin has declaration site variance. I would put out
at the Resource class declaration. Then when you declare your type Flow<Resource<List<RemoteData>>>
, it will already be implicitly out List<RemoteData>
.
Also, your Resource classes look convoluted to me. If data
is the loaded resource, it should not be part of the Loading or Error classes. Why force every instance of Loading and Error to carry a meaningless null data
value? Likewise, the message
should not be part of the Loading and Success cases.
I would rewrite your sealed class as a sealed interface (since it has no shared state between types) like this, and take advantage of data class features as well. Loading
can be an object
because it doesn't need to hold state. Loading and Error can both be Resource<Nothing>
since the type T
is irrelevant to any specific instance of them. That way you won't have to needlessly specify types when using them, like having to put <RemoteData>
after is Resource
or is Error
in a when
statement.
sealed interface Resource<out T> {
object Loading: Resource<Nothing>
data class Success<out T>(val data: T): Resource<T>
data class Error(val message: String): Resource<Nothing>
}
This version of the sealed classes will be much easier to use. The compiler will be more lenient with how and where you need to specify generic types.