#android #kotlin #android-room
#Android #kotlin #android-комната
Вопрос:
У меня проблема с местом.
Я использую обновление с помощью Gson converter для rest api, и я хотел бы поделиться pojos с room. В целом это работает, но в некоторых случаях мне нужно игнорировать некоторые поля, потому что у меня есть список объектов. Я пытался использовать аннотацию @Ignore, но при ее использовании процесс сборки завершается неудачей со следующими ошибками:
ошибка: Сущности и Pojos должны иметь доступный для использования общедоступный конструктор. У вас может быть пустой конструктор или конструктор, параметры которого соответствуют полям (по имени и типу). общедоступный сервис конечного класса {
^ ошибка: не удается найти параметр для поля. закрытый конечный java.lang.Идентификатор строки = null;
^ ошибка: не удается найти параметр для поля. закрытый конечный java.lang.Имя строки = null;
^ ошибка: не удается найти параметр для поля. закрытый конечный java.lang.Описание строки = null;
Итак, используя этот класс, все работает:
@Entity(tableName = "services")
data class Service(
@PrimaryKey val id: String,
val name: String,
val description: String,
val parentId: String?
)
При этом происходит сбой:
@Entity(tableName = "services")
data class Service(
@PrimaryKey val id: String,
val name: String,
val description: String,
val parentId: String?,
@Ignore val test: String
)
Я использую эту версию room:
implementation 'androidx.room:room-runtime:2.1.0-alpha06'
kapt 'androidx.room:room-compiler:2.1.0-alpha06'
Я знаю, что проблему можно было бы устранить, используя var вместо val и добавив дополнительный конструктор, но я не хочу этого делать, я предпочитаю сохранять неизменяемое состояние моих полей.
Это ошибка аннотации ignore? Почему без этого все работает? Любая помощь приветствуется 🙂
Ответ №1:
Во втором примере сервис будет переведен в класс Java, который имеет один конструктор с четырьмя параметрами. Room видит аннотации @Ignore и знает, что ему нужно связать 3 поля, и поэтому ему нужен конструктор с 3 параметрами, соответствующими этим типам полей. Поскольку он не находит такой конструктор (или конструктор по умолчанию), он завершается с ошибкой.
Попробуйте сделать последнее свойство необязательным и использовать аннотацию @JvmOverloads в конструкторе:
@Entity(tableName = "services")
data class Service @JvmOverloads constructor(
@PrimaryKey val id: String,
val name: String,
val description: String,
val parentId: String?,
@Ignore val test: String? = null
)
Это заставит компилятор Kotlin сгенерировать конструктор с тремя параметрами и снова сделать Room счастливым.
Я использую обновление с помощью Gson converter для rest api, и я хотел бы поделиться pojos с room.
Вероятно, вам следует избегать этого и использовать два набора классов для моделирования ответа API и данных базы данных. Даже в этот начальный момент вам нужно сделать несколько «взломов», чтобы все заработало, если в будущем API или база данных изменятся, вам нужно будет внести более сложные изменения в большем количестве мест.
Комментарии:
1. Спасибо, это работает! Насчет того, что нужно иметь 2 набора классов, я понимаю вашу точку зрения, но я хотел бы иметь максимально чистый код. В любом случае, спасибо за совет.
Ответ №2:
На самом деле, вы можете сохранить неизменность с помощью одного класса и без @JvmOverloads
хитрости. Вам просто нужен единственный видимый (для помещения) конструктор для сопоставления полей таблицы. Для вашего примера это было бы:
@Entity(tableName = "services")
data class Service @Ignore constructor(
@PrimaryKey val id: String,
val name: String,
val description: String,
val parentId: String?,
@Ignore val test: String
) {
constructor(id: String, name: String, description: String, parentId: String?) :
this(id, name, description, parentId, /* some default value for test */)
}
Комментарии:
1. Спасибо, это идеальное решение! Почему это не является частью официальной документации ?!? (риторический вопрос)