问题
I am using Firebase Google authentication for login, and I had a list of data points associated with a user. The user populates their data by creating elements in a logged-in session, and these update a list in Firebase that is stored under their uid in a 'user' reference of the RTDB.
Key points:
- When I log out, the data persists.
- When I log back in, the uid is the same in the RTDB
- When I log back in, the user-specific list is deleted.
How can I make the data persist in the 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
EDIT: I was under the impression that the write function would not overwrite the existing data. How can I add to the users reference a specific user's data upon Google login without overwriting whatever information they already have?
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("\\");
}
回答1:
The problem is in your writeNewUser() method. It looks like this is called every time the user authenticates - not just the first time (which the "new user" would suggest).
You have three options:
Restructure your code so you check to see if the user exists, and then only writes the user info if it does not exist.
Restructure your code so only changed data is updated.
Restructure your data so user information is stored one level deeper - thus overwriting it doesn't change any of the sibling nodes.
You could implement 3 with something like:
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);
}
回答2:
You are overwriting the data because you are using the setValue()
method. In stead of using that method, use updateChildren()
method and your problem will be solved.
Hope it helps.
回答3:
To check if a user exists in Firebase Realtime Database before adding one upon user login/registration in 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) {}
});
}
I got the tip from here and the guidance of @Prisoner's answer.
来源:https://stackoverflow.com/questions/44621301/android-firebase-user-specific-real-time-data-is-removed-when-user-logs-back-in