Search code examples
androidkotlinandroid-room

Android room DAO interface does not work with inheritance


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)
    }
}

This results in

An abstract DAO method must be annotated with one and only one of the following annotations: Insert,Delete,Query,Update,RawQuery

However, Marker is not marked with @Dao and FooDao override getSpecialFoo already. Why does this error still show?

I need Marker because I need a generic DAO that has some methods. Is there a way to work around this?

The only way I can think of is marking the dao to Any and cast the type runtime or build a wrapper for the DAO.


Solution

  • This seems like it is limitation of the Room library. You can work around it like the following.

    @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()
    }
    

    When you need it to be Marker<Foo>, you can wrapper() to create a wrapper which implement Marker<Foo> by the dao.