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
我试过了:
- 我确保类型正确(结果 ID 不是来自其他库)
- 要在主线程上创建函数运行,但无法从主线程调用DB
问题是不允许在挂起函数中使用 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)
}
简介:
我按照这个例子创建了一个 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
我试过了:
- 我确保类型正确(结果 ID 不是来自其他库)
- 要在主线程上创建函数运行,但无法从主线程调用DB
问题是不允许在挂起函数中使用 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)
}