David Yuan David Yuan - 19 days ago 10
Android Question

Android: wait for firebase valueEventListener

I am trying to use Semaphore to wait for my firebase valueEventListener. I have an user info activity with 6 different fields that the user must fill out. When the user saves his/her info, I want to do an "all or nothing" type of check. Certain user info cannot be duplicated...for example user name, email, and phonenumber. I am using firebase and currently the general idea is of the format:

void saveUserInfo(){
if(field1 exist in database){
return;
}
.
.
.
if(field6 exist in database){
return;
}

savefield1();
.
.
.
savefield6();
}


The issue I am having is in the method that checks whether or not the value already exists in the database. Here is my current method:

public boolean alreadyInUse(String key, String value) throws InterruptedException {

final StringBuilder done = new StringBuilder("");
final Semaphore semaphore = new Semaphore(0);

mDatabase.child(key).child(value).addListenerForSingleValueEvent(new ValueEventListener() {

@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String result = dataSnapshot.getValue(String.class);
if(result == null){
Log.d("WorkoutLog", "result: null");
done.append("false");
semaphore.release();
return;
}
else if(result.equals(uID)){
Log.d("WorkoutLog", "result: " + result.toString());
done.append("false");
semaphore.release();
return;
}
else{
Log.d("WorkoutLog", "result: " + result.toString());
done.append("true");
semaphore.release();
return;
}

}

@Override
public void onCancelled(DatabaseError databaseError) {

}
});


semaphore.acquire();
if(done.equals("true")){
return true;
}
else if(done.equals("false")){
return false;
}
else{
Log.d("WorkoutLog", "Shouldn't be here");
return true;
}

}


Right now the semaphore is not releasing...Was wondering if anyone can help me out here. Without the semaphore, the return statement will fire before the firebase query can complete...

Answer

The listener callback methods run on the main thread. If you call alreadyInUse() on the main thread, it will block the thread at semaphore.acquire(), preventing the callbacks from running and releasing the semaphore.

You might find this answer to a related question helpful.

Comments