Reputation: 568
INTRODUCTION:
I created an android project following this example: https://github.com/android/architecture-samples/
I had to add a class that holds the response status(Success/Error) and it's value, in the repository it looks basically like this:
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}
It is meant to be better than classic:
class Result<T> (
val success: Boolean,
val data: T?,
val exception: Exception?
)
Because :
- In this case the Success result definitely has only data
and the Error only exception
.
- As both Success and Error Message are inheriting from Result, due to Kotlin Smart Casts, the validation looks simpler:
var responce: Result<DataEntity> = dataSource.GetData()
if (responce is Success) {
doSomethingWith(responce.data)
} else if (responce is Error) {
throw responce.exception
}
PROBLEM:
All good, but when i'm trying to asynchronously observe data from a local dataSource (using Room lib):
interface TaskDao {
@Query("SELECT * FROM tasks")
fun observeTasks(): LiveData<List<TaskEntity>>
}
class SqlLocalDataSource(
private val taskDao: TaskDao,
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
): LocalDataSource {
override suspend fun observeTasks(): LiveData<Result<List<TaskEntity>>> = withContext(ioDispatcher) {
taskDao.observeTasks().map {
Success(it)
}
}
}
It gives me the following Error: Type inference failed. Expected type mismatch: inferred type is LiveData<Result.Success<List<TaskEntity>>> but LiveData<Result<List<TaskEntity>>> was expected
Which is strange because Success inherits from Result
I TRYED:
Upvotes: 1
Views: 734
Reputation: 170713
It gives me the following Error:
Type inference failed. Expected type mismatch: inferred type is LiveData<Result.Success<List<TaskEntity>>> but LiveData<Result<List<TaskEntity>>> was expected
Which is strange because Success inherits from Result
But LiveData<Success<...>>
does not inherit from LiveData<Result<...>>
. Please read about variance and take into account that LiveData
is declared in Java and so can't be covariant.
I don't know why type inference would fail with suspend
and work without it, but the problem can be fixed by being more explicit about types:
taskDao.observeTasks().map {
Success(it) as Result<List<TaskEntity>>
}
Or better, to avoid a cast:
fun <T> success(x: T): Result<T> = Success(x)
taskDao.observeTasks().map {
success(it)
}
Upvotes: 3
Reputation: 568
The Problem was that its not permitted to Use LiveData in a suspend function, after I changed the function to a non suspended the error disappeared :
override fun observeTasks(): LiveData<Result<List<TaskEntity>>> {
return taskDao.observeTasks().map {
Success(it)
}
}
May be somebody can explain why is it?
Upvotes: 1