Есть ли способ добавить преобразование типов в 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>)
}
Я обнаружил, что это невозможно по двум причинам:
- Второй конструктор выдает ошибку: «Конфликт объявлений платформы: следующие объявления имеют одинаковую подпись JVM ((Ljava / lang / String;Ljava / lang / String;Ljava / util / List;) V): ...»
- В
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()
функция - я бы действительно хотел избежать этого для каждого объекта, который у меня есть. Есть ли другой способ решить эту проблему?