I'm writing a static method for a program I've been working on to go through the entries in the "graylist" in my Firebase database and check against user input to see if that entry exists. I'm able to locate the entry just fine, but because of some constraints of the way the threads work when reading/writing data from/to Firebase, I'm unable to figure out how to inform the user if the operation was successful or not.
I have the following method:
public static void addUser() {
final boolean [] complete = new boolean[1];
final String email = Tools.getEmail();
DatabaseReference grayRef = FirebaseDatabase.getInstance().getReference().child("graylist");
// Search the graylist for the email specified.
CountDownLatch latch = new CountDownLatch(1); // need this so Parse-Ly doesn't close before event fires
grayRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onCancelled(DatabaseError dbe) {}
@Override
public void onDataChange(DataSnapshot snap) {
Iterable<DataSnapshot> graylist = snap.getChildren();
for(DataSnapshot gray : graylist) {
String uid = gray.getKey();
String em = gray.getValue(String.class);
if(em.equals(email)) {
// We found the one we're looking for. Insert its UID into the whitelist.
DatabaseReference whiteRef = FirebaseDatabase.getInstance().getReference().child("whitelist");
whiteRef.child(uid).setValue(email, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError dbe, DatabaseReference dbr) {
complete[0] = true;
latch.countDown();
if(dbe != null) {
System.err.println("Error adding user to whitelist!");
dbe.toException().printStackTrace();
}
}
});
break;
}
}
if(latch.getCount() > 0) {
complete[0] = false;
latch.countDown();
}
}
});
try {
latch.await(); // wait for event to fire before we move on
} catch(InterruptedException ie) {
System.err.println("ERROR: Add user latch interrupted!");
ie.printStackTrace();
}
if(complete[0]) ParselyMain.createAlert(AlertType.CONFIRMATION, "User Added", "User added to the whitelist!");
else ParselyMain.createAlert(AlertType.INFORMATION, "User Not Found", "That user was not found in the graylist!");
}
I realize how hacky the final boolean array is, but even that is not working for me. The idea was to use a CountDownLatch and only count down when the write is successful. If all entries from the graylist are read and the CountDownLatch is still at 1, then nothing has been written, and it should count down to exit the thread, but the boolean would determine if the operation is successful or not.
The problem is that it seems to reach the if block after my for loop before the onComplete method is called, resulting in it thinking the operation failed (even though my database on Firebase shows otherwise), and the wrong alert is output.
Can anyone think of a better way to handle this so that I can properly inform them if the user was added to the whitelist or if the user was not found?