I would like to leave this answer, in case someone new in Kotlin like me encounters this.
I was learning codelab about Android, and @get:Query
mentioned in the project, which lead me to this question, then after a good research I found this concept relates to Kotlin than Android and it is called Use-site Targets annotation.
Annotation Use-site Targets
Simply put, annotation use-site targets allow any @Annotations
in your source code to end up at a very specific place in your compiled bytecode or in the Java code generated by kapt.
Kotlin supports the following values of the use-site targets that correspond to:
- delegate – a field storing a delegated property
- field – a field generated for a property
- file – a class containing top-level functions and properties defined in that file
- get/set – the property getter/setter
- param – a constructor parameter
- property – the Kotlin's property, it is not accessible from Java code
- receiver – the receiver parameter of an extension function or property
Let's use simple class:
class Example(@param:ColorRes val resId:Int )
We used the use-site of param
with @ColorRes
, that will apply @ColorRes
to the constructor parameter in the generated Java class:
public final class Example {
private final int resId;
public final int getResId() {
return this.resId;
}
public Example(@ColorRes int resId) {
this.resId = resId;
}
}
Let's change the use-site to field
:
class Example(@field:ColorRes val resId:Int )
Now @ColorRes
annotation will be applied to the resId
field of the generated class:
public final class Example {
@ColorRes
private final int resId;
public final int getResId() {
return this.resId;
}
public ViewModel(int resId) {
this.resId = resId;
}
}
By using the use-site of get
:
class Example(@get:ColorRes val resId:Int )
The getter method of resId
field will have the @ColorRes
annotation:
public final class Example {
private final int resId;
@ColorRes
public final int getResId() {
return this.resId;
}
public Example(int resId) {
this.resId = resId;
}
}
So!
In our Android code:
@Dao
interface MovieDao {
@get:Query("select poster_path from Movie")
val popularMovieImageList: LiveData<List<String>>
}
The annotation use-site of get
will require th implementation of MovieDao
to apply Query("...")
to getter method of popularMovieImageList
:
public final class MovieDaoImpl {
private final LiveData<List<String>> popularMovieImageList;
@Query("select poster_path from Movie")
public final LiveData<List<String>> getPopularMovieImageList() {
...
}
}
NOTE: Previous java code is from my imagination, I have no idea how generated implementation for this Dao by Room
will look, just to support my explanation.
So far!
Why @get:Query
instead of @Query
?
Well, from the docs of Android we use @Query
for methods:
Marks a method in a Dao
annotated class as a query method.
And from the docs of Kotlin we don't use the Annotation Use-site targets
for methods but for a property or a primary constructor parameter
:
When you're annotating a property or a primary constructor parameter, there are multiple Java elements which are generated from the corresponding Kotlin element, and therefore multiple possible locations for the annotation in the generated Java bytecode.
As far as I learned in Kotlin, property getter cannot have parameter but instead use methods for that.
I think all other confusions should be clear now.
References: