Firestore: (21.4.1) [CustomClassMapper]: нет установщика / поля - PullRequest
0 голосов
/ 24 марта 2020

У меня есть класс User, который сохраняет некоторые дополнительные данные о пользователе. Эти данные хранятся в / из Firestore. У меня есть пара полей, которые работают (name, surname, lastLogin), но некоторые из них не работают (blocked).

Когда я делаю поле publi c, они работают, но когда я пытаюсь использовать сеттер, это не так. Я попытался очистить сборку и восстановить ее. Я знаю, что это не сохранение поля из-за @Exclude, что предназначено.

Что я делаю не так? Тип поля не имеет значения, я добавил новое поле String, которое выдает то же предупреждение, в то время как name и surname работают.

База данных:

**userid**
  {
    "name" : "John",
    "surname" : "Doe",
    "lastLogin" : **timestamp**,
    "blocked" : true
  }

Класс:

@Keep
public class User
{
    private String name;
    private String surname;
    private Date lastLogin;
    private boolean blocked = false;

    public User()
    {
    }

public String getName()
{
    return name;
}

public void setName(String name)
{
    this.name = name;
}

public String getSurname()
{
    return surname;
}

public void setSurname(String surname)
{
    this.surname = surname;
}

public Date getLastLogin()
{
    return lastLogin;
}

public void setLastLogin(Date lastLogin)
{
    this.lastLogin = lastLogin;
}

@Exclude
public boolean isBlocked()
{
    return blocked;
}

public void setBlocked(boolean blocked)
{
    this.blocked = blocked;
}

Ответы [ 2 ]

1 голос
/ 24 марта 2020

Проблема в вашем коде состоит в том, что конструктор в классе User имеет значение private . Это не правильный способ создания нового экземпляра класса. JavaBeans требует наличия конструктора без аргументов .

Когда Cloud Firestore SDK десериализует объекты, поступающие из базы данных, он требует, чтобы все используемые объекты имели этот publi c конструктор без аргументов, поэтому он может использовать его для создания экземпляра объекта. Поля в объектах устанавливаются с помощью методов установки publi c или прямого доступа к членам publi c, как вы уже попробовали.

Поскольку ваш конструктор является закрытым, SDK действительно не знает, как создать экземпляр этого. Поэтому обязательно изменить его как publi c. Правильный способ создания этого класса должен быть следующим:

class User {
    private String name;
    private String surname;
    private long lastLogin;
    private boolean blocked = false;

    public User() {} //Needed for Cloud Firestore

    public User(String name, String surname, long lastLogin, boolean blocked) {
        this.name = name;
        this.surname = surname;
        this.lastLogin = lastLogin;
        this.blocked = blocked;
    }

    //Getters and setters are not mandatory
}

Также обратите внимание, что установщики и получатели не требуются. Установщики всегда являются необязательными, потому что если для свойства JSON нет установщика, клиент Firebase установит значение непосредственно в поле.


Редактировать:

Согласно вашему комментарию:

, но это не объясняет, почему некоторые поля работают, а другие нет. Это не должно работать вообще, верно?

Да, все верно, все должно работать. Причина, по которой некоторые из них не работают, заключается в том, что свойство blocked в вашем классе User имеет тип boolean, а в вашей базе данных имеет тип String, и это неверно. Оба типа должны совпадать.

А закрытый конструктор связан с экземпляром синглтона, насколько я знаю, конструктор должен быть закрытым, чтобы избежать создания новых экземпляров класса.

Нет , конструктор должен быть опубликован c. Я думаю, что есть недоразумение. Каждый раз, когда вы используете FirebaseDatabase.getInstance(), открывается одно-сокетное соединение между вашим приложением и серверами Firebase. С этого момента весь трафик c между приложением и базой данных проходит через один сокет. Поэтому не имеет значения, сколько раз вы создаете экземпляр, это всегда будет одно соединение. Что касается вашего класса POJO, такой Singleton не нужен, потому что Firebase всегда должен знать, как создать экземпляр этого класса, используя конструктор publi c без аргументов.

0 голосов
/ 24 марта 2020

Попробуйте создать конструктор с параметрами для всех атрибутов класса вместе с непараметрическим конструктором, а затем в классе java, где вы храните в firebase, создайте объект от пользователя и передайте его.

для пример:

 package com.example.spacing.Model;

 public class User {

private String username;
private String phone;
private String id;
private String imageURL;

private String email;

public User(String username, String email ,String phone, String id, String imageURL) {
    this.username = username;
    this.email=email;
    this.phone = phone;
    this.id = id;
    this.imageURL = imageURL;
}

public String getImageURL() {
    return imageURL;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public User() {
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getPhone() {
    return phone;
}

public void setPhone(String phone) {
    this.phone = phone;
}
   }

и

FirebaseDatabase.getInstance().getReference("Users")

.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
                                .setValue(user);
...