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: