Android: wait for firebase valueEventListener

As previously mentioned, you can use Firebase Task API presented on Google I/O 2016.

Task<?>[] tasks = new Task[] {
    saveUserName(username),
    saveFriends(friends),
    saveOtherStuff(stuff)
};

Tasks.whenAll(tasks)
    .continueWithTask(new RollbackIfFailure())
    .addOnCompleteListener(this)
    .addOnFailureListener(this);

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:

public Task<String> saveUserName(final String username) {
    final TaskCompletionSource<String> tcs = new TaskCompletionSource<>();

    mDatabase.child("users")
        .child(username)
        .addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String username = dataSnapshot.getValue(String.class);
            if (null == username) {
                tcs.setResult(null);
            } else {
                tcs.setException(new IllegalStateException(username));
            }
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
            tcs.setException(new IOException(TAG, firebaseError.toException()));
        }
    });

    return tcs.getTask();
}

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:

class RollbackIfFailure implements Continuation<Void, Task<Void>> {
    @Override
    public Task<Void> then(@NonNull Task<Void> task) throws Exception {

        final TaskCompletionSource<Void> tcs = new TaskCompletionSource<>();

        if (task.isSuccessful()) {
            tcs.setResult(null);
        } else {
            // Rollback everything
        }

        return tcs.getTask();
    }
}

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.