Android会议室DAO界面不适用于继承

Jos*_*hua 6 android kotlin android-room

interface Marker<T : BaseFoo> {
    fun getSpecialFoo(): List<T>
}

@Dao
interface FooDao: Marker<Foo> {
    @Query("SELECT * FROM foo WHERE bar = :bar")
    fun get(bar: Int): List<Foo>

    @Transaction
    override fun getSpecialFoo(): List<Foo> {
        return get(1)
    }
}
Run Code Online (Sandbox Code Playgroud)

这导致

抽象的DAO方法必须使用以下注释之一进行注释:Insert,Delete,Query,Update,RawQuery

但是,Marker尚未标记为@Dao和已FooDao覆盖getSpecialFoo。为什么仍然显示此错误?

我需要,Marker因为我需要具有某些方法的通用DAO。有办法解决这个问题吗?

我能想到的唯一方法是将dao标记为Any并转换类型运行时或为DAO构建包装器。

Bel*_*loo 6

您可以解决。

问题不在于房间限制,而在于kotlin实现本身。您正在使用通用收集方法,默认情况下该方法将处理为List<? extends T>Java实现,但被覆盖的方法具有List<Foo>返回类型。Room Generator匹配方法签名,并且找不到具有相同签名的已实现方法,因此您得到

一个抽象 DAO方法必须与一个且仅以下注释中的一个来注释

解决的方法是在接口中注释方法参数@JvmSuppressWildcards

fun getSpecialFoo(): List<@JvmSuppressWildcards T>

  • 提示:如果你的 BaseDao 有 @Transaction 注解的方法,那么你需要让你的 `ConcreteClassDao` 不是一个接口,而是一个抽象类。 (2认同)

Jos*_*hua 2

这似乎是 Room 库的限制。您可以像下面这样解决它。

@Dao
interface FooDao {
    @Query("SELECT * FROM foo WHERE bar = :bar")
    fun get(bar: Int): List<Foo>

    @Transaction
    fun getSpecialFoo(): List<Foo> {
        return get(1)
    }
}

fun FooDao.wrapper(): Marker<Foo> {
    return Wrapper(this)
}


private class Wrapper(private val dao: FooDao): Marker<Foo> {
    override fun getSpecialFoo() = dao.getSpecialFoo()
}
Run Code Online (Sandbox Code Playgroud)

当您需要它时Marker<Foo>,您可以wrapper()创建一个Marker<Foo>dao.

  • 解决方案,但不如使用“@JvmSuppressWildcards”那么干净 (2认同)