3 回答
TA贡献1796条经验 获得超10个赞
在常规JVM上,可以使用常规Java同步原语来实现。
例如:
// create a java.util.concurrent.Semaphore with 0 initial permits
final Semaphore semaphore = new Semaphore(0);
// attach a value listener to a Firebase reference
ref.addValueEventListener(new ValueEventListener() {
// onDataChange will execute when the current value loaded and whenever it changes
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// TODO: do whatever you need to do with the dataSnapshot
// tell the caller that we're done
semaphore.release();
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
// wait until the onDataChange callback has released the semaphore
semaphore.acquire();
// send our response message
ref.push().setValue("Oh really? Here is what I think of that");
但这在Android上不起作用。这是一件好事,因为在影响用户界面的任何事物中使用这种类型的阻止方法都是一个坏主意。我留下这些代码的唯一原因是因为我需要进行单元测试。
在实际的面向用户的代码中,您应该采用事件驱动的方法。因此,我会“当数据进入时,发送我的消息”,而不是“等待数据到达然后发送我的消息”:
// attach a value listener to a Firebase reference
ref.addValueEventListener(new ValueEventListener() {
// onDataChange will execute when the current value loaded and whenever it changes
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// TODO: do whatever you need to do with the dataSnapshot
// send our response message
ref.push().setValue("Oh really? Here is what I think of that!");
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
最终结果是完全相同的,但是此代码不需要同步,并且在Android上不会阻塞。
TA贡献1836条经验 获得超13个赞
import com.google.android.gms.tasks.Tasks;
Tasks.await(taskFromFirebase);
TA贡献1780条经验 获得超5个赞
我想出了另一种同步获取数据的方式。前提条件是不在UI线程上。
final TaskCompletionSource<List<Objects>> tcs = new TaskCompletionSource<>();
firebaseDatabase.getReference().child("objects").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Mapper<DataSnapshot, List<Object>> mapper = new SnapshotToObjects();
tcs.setResult(mapper.map(dataSnapshot));
}
@Override
public void onCancelled(DatabaseError databaseError) {
tcs.setException(databaseError.toException());
}
});
Task<List<Object>> t = tcs.getTask();
try {
Tasks.await(t);
} catch (ExecutionException | InterruptedException e) {
t = Tasks.forException(e);
}
if(t.isSuccessful()) {
List<Object> result = t.getResult();
}
我测试了我的解决方案,它工作正常,但请证明我错了!
- 3 回答
- 0 关注
- 736 浏览
添加回答
举报