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.
You can solve it.
The issue is not in room restrictions, but in the kotlin implementation itself. You are using generic collection method, which by default is processed to List<? extends T>
java implementation, but overridden method has List<Foo>
return type. Room generator matches a method signature and can't find an implemented method with the same signature, so you get
An abstract DAO method must be annotated with one and only one of the following annotations
The solution is just to annotate a method result type in the interface with @JvmSuppressWildcards
:
fun getSpecialFoo(): List<@JvmSuppressWildcards T>
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With