从 Room 返回接口的 LiveData?
Returning LiveData of an Interface from Room?
TL;DR版本
我想要一个方法,其 returning 签名是 LiveData<User>
,其中 User
是一个接口。实现 return 是一个 LiveData<UserEntity>
,其中 UserEntity
是扩展 User
的具体 class。喜欢以下内容:
fun getUser(id: String): LiveData<User> {
// for brevity
return LiveData<UserEntity>() // actual code will retrieve data from db
}
编译器报错return type not match error
TL;版本
我正在阅读 Jetpack guide。在其中,他们设计了一个 DataRepository
class 可以从 DB 或 WebService 中检索数据,如下图所示:
他们声称
Notice that each component depends only on the component one level below it.
这是一个吸引人的设计,我实际上试图在我自己的项目中复制它。 但是,我发现WebService
不可避免地依赖于Room
,因为它的方法getUser()
return是[=的LiveData
16=],这是一个 房间实体。
这个问题可能不会破坏应用程序,但它与"separation of concerns" 原则的基本设计相矛盾,恕我直言,在美学上很丑陋。
我的问题是:有什么解决方法吗?我试图将 User
重构为一个接口,并实现了一个 UserEntity
class 来扩展它。如下所示:
interface User {
val id: String
val name: String
val lastName: String
}
@Entity(tableName="users")
data class UserEntity(
override val id: String
override val name: String
override val lastName: String) : User
@Dao
interface UserDao() {
@Query("SELECT * FROM users where id = :id")
fun getUser(id: String): LiveData<UserEntity> // UserEntity instead of User, because Room doesn't know how to construct an interface
}
注意我必须 return UserEntity
而不是 User
,因为 Room 不知道如何构建接口。
这是问题所在:以下代码无法编译:
interface DataRepository {
fun getUser(id: String): LiveData<User>
}
class DbRepository : DataRepository {
// ... init db connection/userDao ...
override fun getUser(id: String): LiveData<User> = userDao.getUser(id)
}
错误提示
data type mismatch: LiveData<User> vs. LiveData<UserEntity>
以上代码将不起作用,因为您不能指望一个函数可以 return 多种数据类型。我建议使用一个用户 class,它合并了 Room 和 GSON 映射。
@Entity(tableName="users")
data class Users(
@PrimaryKey // Room annotation
@SerializedName("id") // Gson annotation
val id: String,
@ColumnInfo(name = "name")
@SerializedName("name")
val name: String,
@ColumnInfo(name = "lastName")
@SerializedName("lastName")
val lastName: String,
)
您可以删除您的 UserEntity class 并将上面的内容用作 API 和数据库存储库的 DTO。
TL;DR版本
我想要一个方法,其 returning 签名是 LiveData<User>
,其中 User
是一个接口。实现 return 是一个 LiveData<UserEntity>
,其中 UserEntity
是扩展 User
的具体 class。喜欢以下内容:
fun getUser(id: String): LiveData<User> {
// for brevity
return LiveData<UserEntity>() // actual code will retrieve data from db
}
编译器报错return type not match error
TL;版本
我正在阅读 Jetpack guide。在其中,他们设计了一个 DataRepository
class 可以从 DB 或 WebService 中检索数据,如下图所示:
Notice that each component depends only on the component one level below it.
这是一个吸引人的设计,我实际上试图在我自己的项目中复制它。 但是,我发现WebService
不可避免地依赖于Room
,因为它的方法getUser()
return是[=的LiveData
16=],这是一个 房间实体。
这个问题可能不会破坏应用程序,但它与"separation of concerns" 原则的基本设计相矛盾,恕我直言,在美学上很丑陋。
我的问题是:有什么解决方法吗?我试图将 User
重构为一个接口,并实现了一个 UserEntity
class 来扩展它。如下所示:
interface User {
val id: String
val name: String
val lastName: String
}
@Entity(tableName="users")
data class UserEntity(
override val id: String
override val name: String
override val lastName: String) : User
@Dao
interface UserDao() {
@Query("SELECT * FROM users where id = :id")
fun getUser(id: String): LiveData<UserEntity> // UserEntity instead of User, because Room doesn't know how to construct an interface
}
注意我必须 return UserEntity
而不是 User
,因为 Room 不知道如何构建接口。
这是问题所在:以下代码无法编译:
interface DataRepository {
fun getUser(id: String): LiveData<User>
}
class DbRepository : DataRepository {
// ... init db connection/userDao ...
override fun getUser(id: String): LiveData<User> = userDao.getUser(id)
}
错误提示
data type mismatch: LiveData<User> vs. LiveData<UserEntity>
以上代码将不起作用,因为您不能指望一个函数可以 return 多种数据类型。我建议使用一个用户 class,它合并了 Room 和 GSON 映射。
@Entity(tableName="users")
data class Users(
@PrimaryKey // Room annotation
@SerializedName("id") // Gson annotation
val id: String,
@ColumnInfo(name = "name")
@SerializedName("name")
val name: String,
@ColumnInfo(name = "lastName")
@SerializedName("lastName")
val lastName: String,
)
您可以删除您的 UserEntity class 并将上面的内容用作 API 和数据库存储库的 DTO。