Комната - Использование @get: Query вместо @Query

В этом проекте есть MVVM, Room, Koin и Coroutines.

Код проекта:

@Dao
interface MovieDao {
   @get:Query("select poster_path from Movie")
   val getImgPopularMovieList: LiveData<List<String>>
}

Что означает @get: Query вместо @Query и val вместо fun в интерфейсе DAO?

И как добавить предложение WHERE без функции для передачи параметра или с использованием константы? (Использование обязательно val вместо fun). Пример: выберите poster_path из фильма WHERE category =: someParameterOrConstant


person Lucas Simões Martins    schedule 24.06.2020    source источник
comment
Если вам нужен параметр, вам нужен fun. Что заставляет вас думать, что это не вариант?   -  person ianhanniballake    schedule 24.06.2020
comment
Я предполагаю, что этот тип решения касается Single Sorce of Truth с интеграцией коинов. И для этого есть причина, но я не знаю почему. Я хотел бы хотя бы добавить константу в предложение WHERE, например $ {Constant.category}   -  person Lucas Simões Martins    schedule 24.06.2020
comment
Конечно, можно добавить константу. Что заставляет вас думать, что вы не можете этого сделать?   -  person ianhanniballake    schedule 24.06.2020
comment
Аргумент аннотации должен быть константой времени компиляции. Когда я пытался выбрать backdrop_path из фильма WHERE category = $ {Constant.category}   -  person Lucas Simões Martins    schedule 24.06.2020
comment
Итак, где вы определяете Constant.category? Это на самом деле const?   -  person ianhanniballake    schedule 24.06.2020
comment
Спасибо, что спросили, я этого не осознавал. Я пробовал Enum ... Но я думаю, что это невозможно использовать ... Теперь я не знаю, использую ли я Constant вместо Enum или существует другой способ сделать это. Думаю, если я изменю вал на развлечение, в архитектуре не будет   -  person Lucas Simões Martins    schedule 24.06.2020


Ответы (1)


Я хотел бы оставить этот ответ на случай, если кто-то новый в Котлине, как я, столкнется с этим.

Я изучал codelab об Android и @get:Query упоминал в проекте, который привел меня к этому вопросу, затем после хорошего исследования я обнаружил, что эта концепция относится к Kotlin, а не к Android, и называется аннотация" Цели использования сайта ".


Аннотации Цели использования сайта

Проще говоря, аннотация цели использования сайта позволяет любому @Annotations в вашем исходном коде оказаться в очень конкретном месте в вашем скомпилированном байт-коде или в коде Java, сгенерированном kapt.

Kotlin поддерживает следующие значения целевых объектов использования, которые соответствуют:

  • делегат - поле, хранящее делегированное свойство
  • field - поле, созданное для свойства
  • file - класс, содержащий функции верхнего уровня и свойства, определенные в этом файле
  • get / set - свойство getter / setter
  • param - параметр конструктора
  • property - свойство Котлина, оно недоступно из Java-кода
  • приемник - параметр приемника функции или свойства расширения

Воспользуемся простым классом:

class Example(@param:ColorRes val resId:Int )

Мы использовали use-site param с @ColorRes, который применит @ColorRes к параметру конструктора в сгенерированном классе Java:

public final class Example {

   private final int resId;

   public final int getResId() {
      return this.resId;
   }

   public Example(@ColorRes int resId) {
      this.resId = resId;
   }

}

Давайте изменим use-site на field:

class Example(@field:ColorRes val resId:Int )

Теперь аннотация @ColorRes будет применена к полю resId сгенерированного класса:

public final class Example {

   @ColorRes
   private final int resId;

   public final int getResId() {
      return this.resId;
   }

   public ViewModel(int resId) {
      this.resId = resId;
   }

}

Используя сайт использования get:

class Example(@get:ColorRes val resId:Int )

Метод получения поля resId будет иметь аннотацию @ColorRes:

public final class Example {

   private final int resId;

   @ColorRes
   public final int getResId() {
      return this.resId;
   }

   public Example(int resId) {
      this.resId = resId;
   }

}

So!

В нашем коде для Android:

@Dao
interface MovieDao {

   @get:Query("select poster_path from Movie")
   val popularMovieImageList: LiveData<List<String>>

}

Сайт использования аннотаций get потребует, чтобы реализация MovieDao применила Query("...") к методу получения popularMovieImageList:


public final class MovieDaoImpl {

   private final LiveData<List<String>> popularMovieImageList;

   @Query("select poster_path from Movie")
   public final LiveData<List<String>> getPopularMovieImageList() {
       ...
   }

}

ПРИМЕЧАНИЕ. Предыдущий код Java взят из моего воображения, я понятия не имею, как будет выглядеть сгенерированная реализация для этого Dao от Room, просто чтобы поддержать мое объяснение.


Пока!
Почему @get:Query вместо @Query?

Итак, из документации Android мы используем @Query для методов:

Помечает метод в Dao аннотированном классе как метод запроса.

И из документации Kotlin мы не используйте Annotation Use-site targets для методов, но для a property or a primary constructor parameter:

Когда вы аннотируете свойство или параметр первичного конструктора, существует несколько элементов Java, которые генерируются из соответствующего элемента Kotlin, и, следовательно, несколько возможных мест для аннотации в сгенерированном байт-коде Java.

Насколько я узнал из Kotlin, средство получения свойств не может иметь параметра, а вместо этого использует для этого методы.

Я думаю, что теперь все остальные недоразумения должны быть прояснены.


Использованная литература:

person Ahmed Shendy    schedule 09.10.2020