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...
As previously mentioned, you can use Firebase Task API presented on Google I/O 2016.
If each step that makes a modification can run in parallel, you can create a method that returns a
Task
for each one of them as follows:If any of them fail, you need to rollback the operations. Since this can be threated by a single task, you can create a
Continuation
task:The listener callback methods run on the main thread. If you call
alreadyInUse()
on the main thread, it will block the thread atsemaphore.acquire()
, preventing the callbacks from running and releasing the semaphore.You might find this answer to a related question helpful.