Android Firebase: пользовательские данные в реальном времени удаляются при повторном входе пользователя

Я использую проверку подлинности Google Firebase для входа в систему, и у меня был список точек данных, связанных с пользователем. Пользователь заполняет свои данные, создавая элементы во время сеанса, вошедшего в систему, и они обновляют список в Firebase, который хранится под его идентификатором пользователя в ссылке "пользователь" RTDB.

Ключевые моменты:

  1. Когда я выхожу, данные сохраняются.
  2. Когда я снова вхожу в систему, UID совпадает в RTDB
  3. Когда я снова вхожу, пользовательский список удаляется.

Как я могу сохранить данные в RTDB?

UserDataListActivity

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.signout_button:
            FirebaseAuth.getInstance().signOut();
            Log.i(TAG, "User allegedly logged out.");
            Intent backToLogin = new Intent(UserDataListActivity.this, LoginActivity.class);
            startActivity(backToLogin);
            finish();
            break;
    }
}

LoginActivity

РЕДАКТИРОВАТЬ: у меня было впечатление, что функция записи не будет перезаписывать существующие данные. Как я могу добавить к пользователям ссылки на данные конкретного пользователя при входе в Google, не перезаписывая какую-либо информацию, которую они уже имеют?

private void onAuthSuccess(FirebaseUser user) {
    String username = usernameFromEmail(user.getEmail());
    String[] names = firstAndLastNameFromDisplayName(user.getDisplayName());

    // Write new user
    writeNewUser(user.getUid(), names, username, user.getEmail(), user.getUid());

    // Go to MainActivity
    Intent startMainActivity = new Intent(LoginActivity.this, MainActivity.class);
    startActivity(startMainActivity);
    finish();
}
private String usernameFromEmail(String email) {
    if (email.contains("@")) {
        return email.split("@")[0];
    } else {
        return email;
    }
}
private String[] firstAndLastNameFromDisplayName(String fullName) {
    if (fullName != null) {
        if (fullName.contains(" ")) {
            return new String[]{fullName.split(" ")[0], fullName.split(" ")[1]};
        } else {
            return new String[]{fullName, "emptyLastName"};
        }
    } else {
        return new String[]{"defaultfirst","defaultlast"};
    }
}
private void writeNewUser(String userId, String[] names, String username, String email,String uid) {
    User user = new User(username,names[0],names[1], email, uid);
    myUsers.child(userId).setValue(user);
}

private boolean isEmailValid(String email) {
    return email.contains("@");
}

private boolean isPasswordValid(String password) {
    return (password.length() > 4) && !password.contains("\\");
}

введите описание изображения здесь

3 ответа

Решение

Чтобы проверить, существует ли пользователь в базе данных Firebase Realtime, перед его добавлением при входе / регистрации пользователя в Android:

private void writeNewUser(final String userId, String[] names, String username, String email,String uid) {
    final User user = new User(username,names[0],names[1], email, uid);
    myUsers.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (!dataSnapshot.hasChild(userId)) {
                myUsers.child(userId).setValue(user);
            }
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });

}

Отсюда я получил подсказку и руководство по ответу @Prisoner.

Проблема в вашем методе writeNewUser(). Похоже, что это вызывается каждый раз, когда пользователь проходит аутентификацию, а не только в первый раз (что предложил бы "новый пользователь").

У вас есть три варианта:

  1. Перестройте ваш код, чтобы проверить, существует ли пользователь, а затем записать информацию о пользователе, только если он не существует.

  2. Перестройте ваш код, чтобы обновлялись только измененные данные.

  3. Перестройте ваши данные так, чтобы информация о пользователях сохранялась на один уровень глубже - таким образом, перезапись ее не меняет ни одного из соседних узлов.

Вы могли бы реализовать 3 с чем-то вроде:


private void writeNewUser(String userId, String[] names, String username, String email,String uid) {
    User user = new User(username,names[0],names[1], email, uid);
    myUsers.child(userId).child("userInfo").setValue(user);
}

Вы перезаписываете данные, потому что используете setValue() метод. Вместо того, чтобы использовать этот метод, используйте updateChildren() метод и ваша проблема будет решена.

Надеюсь, поможет.