Android 房间 DAO 接口不适用于继承

Posted

技术标签:

【中文标题】Android 房间 DAO 接口不适用于继承【英文标题】:Android room DAO interface does not work with inheritance 【发布时间】:2019-03-14 23:40:49 【问题描述】:
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)
    

这会导致

抽象 DAO 方法必须使用以下注释中的一个且仅一个注释:Insert、Delete、Query、Update、RawQuery

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

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

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

【问题讨论】:

@IntelliJAmiya 这是我在 *** 上输入的一个错字。已编辑。 【参考方案1】:

你可以解决它。

问题不在于房间限制,而在于 kotlin 实现本身。您正在使用泛型集合方法,默认情况下处理为 List&lt;? extends T&gt; java 实现,但被覆盖的方法具有 List&lt;Foo&gt; 返回类型。房间生成器匹配方法签名,找不到具有相同签名的实现方法,所以你得到

abstract DAO 方法必须用一个且只有一个注释 以下注释

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

fun getSpecialFoo(): List&lt;@JvmSuppressWildcards T&gt;

【讨论】:

最佳答案。如果这是一个直接而简单的答案,我不会为 DAO 编写包装器。 提示:如果你的 BaseDao 有 @Transaction 注解的方法,那么你需要让你的 ConcreteClassDao 不是一个接口,而是一个抽象类。 请注意,如果您的非 Room DAO 接口包含 suspend fun foos(): List&lt;@JvmSuppressWildcards Foo&gt;,则生成的 Room DAO 将在生成的 Java 方法上显示 lint 错误:com.example.FooDao_Impl 中的 foos(Continuation&lt;? super List&lt;Foo&gt;&gt;) 与 @987654329 冲突@在com.example.FooDao;两种方法都有相同的擦除,但都没有覆盖另一个。这可能不是问题。无论如何,Java List&lt;E&gt; 与 Kotlin 的 List&lt;out E&gt;(带有抑制通配符)不同。请在此处发表评论,或者如果您认为不同,请回答!【参考方案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()

当您需要Marker&lt;Foo&gt; 时,您可以通过wrapper() 创建一个包装器,该包装器通过dao 实现Marker&lt;Foo&gt;

【讨论】:

一种变通解决方案,但不如使用@JvmSuppressWildcards

以上是关于Android 房间 DAO 接口不适用于继承的主要内容,如果未能解决你的问题,请参考以下文章

Spring依赖注入不适用于继承

Android 房间 rawquery 问题

FFMPEG 命令不适用于 Android 10

Forge 数据可视化不适用于 Revit 房间 [ITA]

房间数据库 RawQuery() 不适用于“IN”和“NOT IN”子句

插入房间后的行