我正在尝试使用信号量来等待我的firebase valueEventListener。我有一个用户信息活动与6个不同的领域,用户必须填写。当用户保存他/她的信息时,我想做一个“全有或全无”类型的检查。某些用户信息不能是duplicated...for例如用户名、电子邮件和电话号码。我使用的是firebase,目前的总体思路是:
void saveUserInfo(){
if(field1 exist in database){
return;
}
.
.
.
if(field6 exist in database){
return;
}
savefield1();
.
.
.
savefield6();
}
我遇到的问题是检查数据库中是否已经存在该值的方法。下面是我当前的方法:
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;
}
}
现在信号量不是releasing...Was,不知道有没有人能帮我。如果没有信号量,则返回语句将在firebase查询完成之前触发...
发布于 2016-08-16 11:46:42
侦听器回调方法在主线程上运行。如果在主线程上调用alreadyInUse()
,它将阻塞semaphore.acquire()
处的线程,阻止回调运行并释放信号量。
您可能会发现相关问题的this answer很有帮助。
发布于 2016-11-15 01:35:07
如前所述,您可以使用Google I/O 2016上提供的Firebase Task API。
Task<?>[] tasks = new Task[] {
saveUserName(username),
saveFriends(friends),
saveOtherStuff(stuff)
};
Tasks.whenAll(tasks)
.continueWithTask(new RollbackIfFailure())
.addOnCompleteListener(this)
.addOnFailureListener(this);
如果进行修改的每个步骤都可以并行运行,则可以创建一个方法,为每个步骤返回一个Task
,如下所示:
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();
}
如果其中任何一个失败,您需要回滚操作。由于这可能会受到单个任务的威胁,因此您可以创建一个Continuation
任务:
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();
}
}
https://stackoverflow.com/questions/38966056
复制相似问题