Reputation: 43
I am trying to make a function that checks if a username is taken or if it is available, how I have it in firestore is that the UniqueID is the username and not a field. This is the function:
private boolean checkUsernameValidity(String enteredUsername) {
/**
* Create code for querying through firestore DB for enteredUsername
*/
final boolean[] usernameAvailable = {true};
String USERTAG = "User documents";
Log.d("Entered Username: ", enteredUsername);
DocumentReference userDocRef = users.document(enteredUsername);
userDocRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document.exists()) {
Log.d(USERTAG, "DocumentSnapshot data: " + document.getData());
Log.d("Warning", "Uh oh username is taken");
usernameAvailable[0] = false;
Toast.makeText(CreateAccount.this,
"This username is taken! Please enter a different username",
Toast.LENGTH_SHORT)
.show();
} else {
Log.d(USERTAG, "No such document, This Username is available");
}
} else {
Log.d(USERTAG, "get failed with ", task.getException());
}
}
});
/**
* If there was a user with entered username found already;
*/
if(!usernameAvailable[0]) {
return false;
}
if (enteredUsername.length() < 5) {
Toast.makeText(CreateAccount.this, "This username is too short",
Toast.LENGTH_SHORT)
.show();
return false;
}
Log.d("Status", "All Good!");
return true;
}
The function returns true according to the debugger before the usernameAvailable[0] is changed. Picture here:
In the picture, the Log of a successful status is printed before the log that says that the username was taken. I'm guessing that the function needs to be an asynchronous or something along those lines but I'm not 100% on creating asynchronous methods. How do I make it so that my function retrieves the document if it exists and sets my usernameAvailable[0] to false inside the get document function before going through the rest of the checkUsernameValidity method.
P.S. usernameAvailable is a final array of booleans instead of just a boolean because it is accessed inside inner class
Upvotes: 0
Views: 48
Reputation: 5990
What you said is on the right track. The get()
call you're making on the DocumentReference
internally starts an asynchronous task which defers the network request to a background thread. If this wasn't the case then you would have a non-responsive app for the time it takes to receive the result. So instead of receiving the result synchoronously, in your code you attach an OnCompleteListener<*>
which Firebase uses to call your onChanged
method once the request is complete so that you can handle the result.
For a simple solution you can implement some sort of callback into checkUsernameValidity
to process the result from wherever you are calling from. An implementation would look something like this:
interface Callback {
void onResult(boolean valid);
}
void checkUsernameValidity(Callback callback) {
userDocRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
callback.onResult(true);
}
});
}
I would recommend doing some research on asynchronicity and the basic concept of callbacks.
Upvotes: 2