无法反序列化对象。类未定义无参数构造函数。如果您使用 ProGuard,请确保这些构造函数未被剥离

NEU*_*USA 1 android kotlin firebase google-cloud-firestore

https://github.com/neuberfran/JThings/blob/main/app/src/main/java/neuberfran/com/jfran/model/FireFran.kt

我有这个 POJO 上面提到了主题中提到的错误。我知道这是这里已经提到的错误,但是我尝试了几个类(除了这个类)但我没有成功,因为我的模型/POJO 类(和代码实现)与我看到的几个不同:(每个帮助欢迎)

无法反序列化对象。类没有定义无参数构造函数。如果您使用 ProGuard,请确保这些构造函数没有被剥离(在字段“值”中找到)

在此处输入图片说明 在此处输入图片说明 对garagem 文件进行了更改,用valorb 交换了价值,等等......

在此处输入图片说明

Ale*_*amo 5

错误很明显,您的类“FireFran”没有无参数构造函数。当您尝试从 Cloud Firestore 反序列化对象时,Android SDK 要求该类必须具有默认的无参数构造函数以及映射到每个数据库属性的 ​​setter。

在 Kotlin 中,数据类不提供默认的无参数构造函数。所以你需要以某种方式确保编译器所有属性都有一个初始值。您可以为所有属性提供初始值 null 或您认为更合适的任何其他值。

所以你的“FireFran”可能是这样的:

class FireFran(
    var alarmstate: Boolean  = false,
    var garagestate: Boolean = false,
    var id: String? = null,
    var userId: String? = null,
    var value: FireFranValue? = null //Newly added
) {
    //var value: FireFranValue = FireFranValue(false, 0)
    companion object Factory {
        fun create() :FireViewModel = FireViewModel()
        var COLLECTION = "device-configs"
        var DOCUMENT = "alarme"
        var FIELD_userId = "userId"
    }
}
Run Code Online (Sandbox Code Playgroud)

现在在构造函数中添加属性,Kotlin 将自动生成一个默认的无参数构造函数。这样,Firebase Android SDK 就可以使用了。它还将为每个属性生成设置器。请注意,每个属性都是var而不是 val,并在“id”和“userId”的情况下提供默认空值。

如果不进行此更改,您将无法使用自动反序列化。您必须从DocumentSnapshot对象中读取每个属性的值,并将它们全部传递给 Kotlin 的构造函数。

编辑:

  1. 在您的屏幕截图中,“value”属性位于“FireFranValue”类型的对象上,该对象只有“brightness”和“on”两个属性。为了能够读取“value”下的数据,您的“FireFran”类应该包含一个“FireFranValue”类型的新属性。请检查上面的类。

  2. 如果不想使用自动反序列化,可以单独获取每个属性的值。例如,您可以使用 DocumentSnapshot 的getString(String field)方法获取“userId”属性的值:

     val userId = snapshot.getString("userId")
    
    Run Code Online (Sandbox Code Playgroud)

编辑2:

你的三个类应该是这样的:

class FireFran(
    var alarmstate: Boolean  = false,
    var garagestate: Boolean = false,
    var id: String? = null,
    var userId: String? = null,
    var owner: String? = null,
    var value: FireFranValue = FireFranValue(false),
    var valorb: FireFranValueB = FireFranValueB(openPercent = 0)
)
data class FireFranValue(
    var on: Boolean // = false
)

data class FireFranValueB(
    var openPercent: Number // = 0
)
Run Code Online (Sandbox Code Playgroud)

编辑3:

class FireFran(
    var alarmstate: Boolean  = false,
    var garagestate: Boolean = false,
    var id: String? = null,
    var userId: String? = null,
    var owner: String? = null,
    var value: FireFranValue? = null,
    var valorb: FireFranValueB? = null
)
data class FireFranValue(
    var on: Boolean? = null
)

data class FireFranValueB(
    var openPercent: Number? = null
)
Run Code Online (Sandbox Code Playgroud)

现在,“on”和“openPercent”将从数据库中获取值。

请检查以下类声明:

  • 我不确定这些更改与您最初的问题有何关系,但整个想法是为类和内部类提供无参数构造函数。请随时通知我。 (3认同)
  • 于见。请检查我的最后编辑(Edit3)。现在有用吗? (3认同)
  • 是的,FireFran 和 FireFranValue 都必须具有无参构造函数。对于“value”,您还应该在类中添加另一个 FireFranValue 类型的属性。现在有用吗? (2认同)
  • 请检查我更新的答案。现在清楚了吗? (2认同)
  • 是的,在该图像中我看到了变量命名问题。因此,这些字段应保持“值”,就像在数据库中一样,并更改第二个字段。或者简单地注释第 14 行。现在可以使用吗? (2认同)
  • 创建“FireFranValue”类的新对象并没有帮助。除此之外,所有对象都应该有**不同的名称**。再试一次。 (2认同)
  • 是的,所有对象都应该有不同的名称。不可能有两个同名的字段。Tou 在代码“FireFranValueB”中添加了一个新类。该类和相应的属性“valorb”(来自数据库)不会解决您的实际问题。如果您需要一个名为“valorb”的新属性,则应将该属性映射到“FireFranValueB”类型的对象。但你的班级中仍然需要有不同的名字,对吗? (2认同)
  • 请检查我更新的答案。现在有用吗? (2认同)
  • 有了新的改变,你能得到想要的数据吗?伴生对象可以放置在类中。 (2认同)
  • 很高兴听到你成功了;) (2认同)
  • 现在究竟还剩下什么? (2认同)
  • 我可以看看这个**[answer](/sf/ask/4250385401/#60719948)**,有帮助吗? (2认同)
  • “openPercent”不是一个数字吗?除此之外,所有类都应该添加到 ProGuard 规则中,包括子类。 (2认同)
  • @NEUBERSOUSA 你的新课程对我来说看起来不错。现在有什么问题吗? (2认同)

小智 0

第一件事:没有必要创建名为 valorb 的字段(地图类型)。它已通过 value.openPercent 解决

由于我有两个文档(alarme 和 Garagem),我创建了两个 POJO 类(FireFran 和 FireFranB)

https://github.com/neuberfran/JThingsFinal/blob/main/app/src/main/java/neuberfran/com/jfran/model/FireFranB.kt

秘密是将 value.on 和 value.openPercent 字段视为映射(事实如此)

在此输入图像描述