将数据从 dataSnapshot 解析为 class 是如何工作的?

How does Parsing data from dataSnapshot into a class work?

我曾经使用像这样的地图来解析 dataSnapshots Map<String, Object> map = (Map<String, Object>) dataSnapshot.getValue();

但是当我在 YouTube 上观看教程时,我看到有人像这样使用 class 解析 dataSnapshot User user = dataSnapshot.getValue(User.class);,现在我有很多问题。

这是如何运作的?

我的意思是,如果 class 用户的成员与快照中的成员不同,会不会给我们带来错误?

例如

snapshot:
-User
 |-Name:jojo
 |-Age:19

User Class fields:
 boolean a;
 float x;
 int c;

如果 class 用户的字段顺序与快照中的字段顺序不同且大小写不同,或者如果 class 缺少一个字段怎么办?

第二个问题的例子:

snapshot:
-User
 |-Name:jojo
 |-Age:19

User Class fields:
 int age;
 String name;

我已阅读 firebase 文档 https://firebase.google.com/docs/reference/android/com/google/firebase/database/DataSnapshot#getValue(java.lang.Class) 但它没有回答我的两个问题它只是说 class 必须有一个空构造函数和每个字段 getter

编辑:

snapshot:
-User
 |-Followers
  |-id:xxxxxx
  |-id:xxxxxx
 |-Name:jojo
 |-Age:19

User Class fields:
 int age;
 String name;

Firebase 尝试使用 JavaBean 命名约定在来自数据库的 JSON 数据中的属性与您的 class 中的属性之间进行映射。映射到数据快照的最简单 class 是:

public static class User {
  public String Name;
  public long Age;
}

这个class对于数据库中的每个属性都有一个public字段,编译器会生成一个默认的no-argument构造函数,这就是Firebase所需要的以便为数据创建 User 个对象。


更常见的模式是为属性创建 getter and/or setter。对于您的两个属性的所有这些,您将获得:

public static class User {
  String Name;
  long Age;

  public String getName() { return Name }
  public void getName(String name) { Name = name }
  public long getAge() { return Age }
  public void setSage(long age) { Age = age }
}

现在有了这些,字段本身不再需要 public,如果需要,我们可以在 get 和 set 方法中做额外的工作。但是属性的名称现在将由那些使用 JavaBean 命名转换的 getter 和 setter 确定,这导致属性 nameage 的大小写与数据库中的不同。

要解决这个问题,您可以在代码中提供注释,说明每个字段的数据库属性是什么:

public static class User {
  String Name;
  long Age;

  @PropertyName("Name")
  public String getName() { return Name }
  @PropertyName("Name")
  public void getName(String name) { Name = name }
  @PropertyName("Age")
  public long getAge() { return Age }
  @PropertyName("Age")
  public void setSage(long age) { Age = age }
}

现在 Firebase 映射器将读取 PropertyName 注释,并能够再次在数据库中的数据和对象中的数据之间正确映射。


如果您的 class 具有比数据库中的数据更多的属性(因此 public 字段或 getters/setters),则当它从数据库中读取数据时,这些属性将保持未填充状态.写入数据库时​​,会将附加属性写入数据库。

如果你想阻止这种情况,你可以使用 @IgnoreExtraProperties annotation.

另见: