【问题标题】:Could not deserialize object. Class does not define a no-argument constructor.If you are using ProGuard, make sure these constructors are not stripped无法反序列化对象。类未定义无参数构造函数。如果您使用 ProGuard,请确保未剥离这些构造函数
【发布时间】:2021-06-24 21:35:47
【问题描述】:

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

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

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

对garagem 文件进行了更改,将价值换成valorb 等等......

【问题讨论】:

    标签: android firebase kotlin google-cloud-firestore


    【解决方案1】:

    第一件事:没有必要创建名为 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 字段视为映射(事实如此)

    【讨论】:

      【解决方案2】:

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

      在 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"
          }
      }
      

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

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

      编辑:

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

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

         val userId = snapshot.getString("userId")
        

      编辑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
      )
      

      编辑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
      )
      

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

      请检查以下类声明:

      【讨论】:

      • 是的,FireFran 和 FireFranValue 都必须有无参数构造函数。对于value,您还应该在类中添加另一个FireFranValue 类型的属性。现在可以用了吗?
      • 请查看我更新的答案。现在清楚了吗?
      • 是的,在那张图片中我看到了一个变量命名问题。所以字段应该保持“值”,就像它在数据库中一样,并更改第二个。或者只是评论第 14 行。它现在有效吗?
      • 我不确定这些更改与您最初的问题有何关系,但整个想法是为类和内部类提供无参数构造函数。随时通知我。
      • 见。请检查我的最后一次编辑(Edit3)。现在可以用了吗?
      猜你喜欢
      • 2020-06-08
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      相关资源
      最近更新 更多