从 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。