问题
I am trying to make a register page. Before registering that user I will try to validate the username and email do not exist in the database. But I somehow cannot set the variable to be false when the username/email already exist so it will end up still registering the user.
How can I do this? Please guide me on this.
Checking if username and email already exist before register user:
if (!checkIfUsernameExists(userName) && !checkIfEmailExists(userEmail)){
registerUser();
}
Method for checking if the username exists or not:
public boolean checkIfUsernameExists(String userName){
boolean isExist = false;
databaseReferenceUser.orderByChild("userName").equalTo(userName).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
editTextUserNameRegister.setError("Username already exists");
editTextUserNameRegister.requestFocus();
final boolean isExist = true;
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
return isExist;
}
Method for checking if the email already exists or not:
public boolean checkIfEmailExists(String userEmail){
boolean isExist = false;
databaseReferenceUser.orderByChild("userEmail").equalTo(userEmail).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
editTextEmailRegister.setError("Email already exists");
editTextEmailRegister.requestFocus();
final boolean isExist = true;
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
return isExist;
}
回答1:
You need your own callback to wait for Firebase to return you data. An example would look like this
Define an interface
public interface UserCallback {
void onUserExists(Boolean exists);
}
Make your method be void and add the callback parameter, making it final so it can be referenced inside the Firebase method
public void checkIfEmailExists(String userEmail, final UserCallback callback){
databaseReferenceUser.orderByChild("userEmail").equalTo(userEmail).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
editTextEmailRegister.setError("Email already exists");
editTextEmailRegister.requestFocus();
callback.onUserExists(true);
} else {
callback.onUserExists(false);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
// return isExist; // this method is void now
}
Now, you must write the other code functionally rather than procedurally.
checkIfUsernameExists(userName, new UserCallback() {
@Override
public void onUserExists(Boolean exists) {
if (!exists) {
checkIfEmailExists(userEmail, new UserCallback() {
// registerUser() if not exists
}
}
}
} );
And if you're storing unique usernames / emails, you should not need to check both
A more complete interface definition can be found here Wait Firebase async retrive data in android
回答2:
I see you are using Firebase, and it would be a much better idea to use FirebaseAuth, which lets you authenticate users on a secure, encrypted and versatile way. If you use the database you may be risking the privacy and security of the user accounts (I assume the passwords aren't encrypted and the accessing rules are not exactly private).
Add in your Gradle file:
compile 'com.google.firebase:firebase-auth:11.6.2'
And then you only have to enable an Email/Password auth:
LoginRegisterActivity.java
1 - Get the instance.
FirebaseAuth mAuth = FirebaseAuth.getInstance();
2 - Get the user. Once it's registered and/or signed in, it will be saved.
FirebaseUser user = mAuth.getCurrentUser();
3 - So let's try to create a new user
mAuth.createUserWithEmailAndPassword(email,password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
//User registered successfully
}else{
// WAIT! SOMETHING WENT WRONG, DESPITE IT IS COMPLETE
}
}
});
4 - If the task is succesful, you can just leave everything like that and finish()
the activity, FirebaseAuth
will save it for you, and you can get the info from anywhere in your app.
5 - But the task may not be successful, and that is because there was already another user in the project with the same email. So inside the else
in onComplete()
you can try to login the user. This is pretty straight-forward as well.
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() {
@Override public void onComplete(@NonNull Task<AuthResult> task) {
//And here you can do whatever you want: create a file on your DB, send a verification email...
});
回答3:
boolean isExist is already defined don't need to declare it again.
public void checkIfEmailExists(String userEmail){
databaseReferenceUser.orderByChild("userEmail").equalTo(userEmail).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
boolean isExist = dataSnapshot.exists();
if (isExist){
editTextEmailRegister.setError("Email already exists");
editTextEmailRegister.requestFocus();
if(isExist){
//call your required method to do next steps
}
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
来源:https://stackoverflow.com/questions/47655849/declaring-a-variable-as-final-for-firebase-function-checking-if-username-and-em