Есть ли способ добавить преобразование типов в DocumentSnapshot.toObject()?

Я хочу сделать мое приложение Kotiln менее связанным с моим компонентом Firestore.

У меня есть модель, которая раньше выглядела так:

      data class MyObjectModel(
    @DocumentId val id: String = "",
    var title: String = "",
    var media: List<String> = listOf()
)

Поскольку он широко используется в приложении, он очень связан с Firestore (например, в списке мультимедиа должны быть URL-адреса, а я использую строки только из-за забавных ограничений DocumentSnapshot.toObject ()). Я читал, что классы данных Kotlin очень проблематичны с наследованием, поэтому я подумал о создании такого интерфейса:

      interface MyObject{
    val id: String
    var title: String
    val media: MutableList<Uri>
}

И используйте его во всем приложении.

Чтобы получить объект из Firestore, я хотел создать POJO, который реализует этот интерфейс следующим образом:

      data class MyObjectPojo(
    @DocumentId override val id: String,
    override var title: String,
    override val media: MutableList<Uri>
) : MyObject {
    constructor(id: String, title: String, media: List<String>) : 
            this(id, title, media.map { Uri.parse(it) } as MutableList<Uri>)
}

Я обнаружил, что это невозможно по двум причинам:

  1. Второй конструктор выдает ошибку: «Конфликт объявлений платформы: следующие объявления имеют одинаковую подпись JVM ((Ljava / lang / String;Ljava / lang / String;Ljava / util / List;) V): ...»
  2. В DocumentSnapshot.toObject() функция вызывает только основной конструктор, который не будет работать в моем случае (поскольку он не поддерживает автоматический синтаксический анализ строк в Uris)

Кроме того, поскольку мой объект будет расти, чтобы иметь больше полей, это перестает быть шаблоном ...

Я придумал решение для этого: удалить второй конструктор и изменить последний параметр основного из override val media: MutableList<Uri> к val mediaStringList: MutableList<String>. Тогда я могу сделать одно из следующих действий в теле класса:

          // Solution 1
    override val media: MutableList<Uri>
        get() = mediaStringList.map { Uri.parse(it) } as MutableList<Uri>

    // Solution 2
    override val media = mediaStringList.map { Uri.parse(it) } as MutableList<Uri>

Оба они уродливы, поскольку первый означает операцию отображения списка для каждого вызова get, а второй означает повторное удержание списка. Я смогу удалить val от mediaStringList параметр, если бы я мог добавить тело в конструктор, но я думаю, что это невозможно по определению основного конструктора ...

Единственный способ, который я сейчас вижу, - это реализовать toMyObject() функции моей собственной, но это также означало бы реализовать другой способ для set()функция - я бы действительно хотел избежать этого для каждого объекта, который у меня есть. Есть ли другой способ решить эту проблему?

0 ответов

Другие вопросы по тегам