首页 > 解决方案 > 有没有办法在 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 调用的列表映射操作,第二个意味着持有列表两次。如果我可以向构造函数添加一个主体,我将能够valmediaStringList参数中删除,但我想根据主构造函数的定义这是不可能的......

我现在看到的唯一方法是实现toMyObject()我自己的函数,但这也意味着为set()函数实现另一种方式——我真的很想避免对我拥有的每个对象都这样做。还有其他方法可以解决这个问题吗?

标签: kotlingoogle-cloud-firestoretype-conversiondata-classprimary-constructor

解决方案


推荐阅读