Android kotlin 类型继承失败



简介:

我按照这个例子创建了一个安卓项目:https://github.com/android/architecture-samples/

我必须添加一个保存响应状态(成功/错误(及其值的类,在存储库中它基本上看起来像这样:

sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}

它意味着比经典更好:

class Result<T> (
val success: Boolean,
val data: T?,
val exception: Exception?
)

因为: - 在这种情况下,成功结果肯定只有data,错误只有exception。 - 由于成功和错误消息都继承自结果,由于 Kotlin 智能强制转换,验证看起来更简单:

var responce: Result<DataEntity> = dataSource.GetData()
if (responce is Success) {
doSomethingWith(responce.data)
} else if (responce is Error) {
throw responce.exception
}

问题:

一切都很好,但是当我尝试异步观察来自本地数据源的数据(使用 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)
}
}
}

它给了我以下错误:Type inference failed. Expected type mismatch: inferred type is LiveData<Result.Success<List<TaskEntity>>> but LiveData<Result<List<TaskEntity>>> was expected

这很奇怪,因为成功继承自结果

我试过:

  • 我确保类型正确(结果 ID 不是来自其他库(
  • 使函数在主线程上运行,但无法从主线程调用 DB

它给了我以下错误:Type inference failed. Expected type mismatch: inferred type is LiveData<Result.Success<List<TaskEntity>>> but LiveData<Result<List<TaskEntity>>> was expected

这很奇怪,因为成功继承自结果

但是LiveData<Success<...>>不会继承LiveData<Result<...>>.请阅读方差,并考虑到LiveData是用 Java 声明的,因此不能是协变的。

我不知道为什么类型推断会在suspend失败并且没有它的情况下工作,但是可以通过更明确地说明类型来解决此问题:

taskDao.observeTasks().map {
Success(it) as Result<List<TaskEntity>>
}

或者更好的是,为了避免石膏转换:

fun <T> success(x: T): Result<T> = Success(x)
taskDao.observeTasks().map {
success(it)
}

问题是不允许在挂起函数中使用 LiveData,在我将函数更改为非挂起函数后,错误消失了:

override fun observeTasks(): LiveData<Result<List<TaskEntity>>> {
return taskDao.observeTasks().map {
Success(it)
}
}

也许有人可以解释为什么?

最新更新