Android kotlin类型继承失败

Android kotlin type inheritance failed

简介:

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

我必须添加一个 class 来保存响应状态 (Success/Error) 和它的值,在存储库中 它看起来基本上是这样的:

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

它意味着比 classic:

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

因为: - 在这种情况下,成功结果肯定只有 data 而错误只有 exception。 - 由于 Kotlin Smart Casts,Success 和 Error Message 都继承自 Result,因此验证看起来更简单:

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

这很奇怪,因为 Success 继承自 Result

我试过了:

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

 override fun observeTasks(): LiveData<Result<List<TaskEntity>>> {
    return 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

但是 LiveData<Success<...>> 而不是 继承自 LiveData<Result<...>>。请阅读 variance 并考虑到 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)
}