我正在编写一个方法,我想查询数据库并在查询完成后执行另一个方法。但是,由于对数据库的调用是异步的,我似乎无法弄清楚如何在数据库调用完成之前停止主要的执行流程,如下所示:
public void getUserFromEmail(String email) {
Firebase usersRef = rootRef.child("users");
//Asynchronous database call, want to stop everything else
usersRef.orderByKey().equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
}
@Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println(firebaseError.getMessage());
}
});
//Perform some more operations after database call is finished
}
我习惯于在Nodejs中使用异步回调,但我无法弄清楚是否有任何等效的方法来控制Java中的执行流程。有没有简单的方法来实现我想做的事情?
答案 0 :(得分:1)
你无法阻止主流,主线程将继续。 (除非你以其他方式阻止它,但这会导致“应用程序无响应”,所以不要)。
只需在回调中执行操作即可。
public void getUserFromEmail(String email) {
Firebase usersRef = rootRef.child("users");
//Asynchronous database call, want to stop everything else
usersRef.orderByKey().equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Perform some more operations after database call is finished
// OR... callSomeMethod();
}
@Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println(firebaseError.getMessage());
}
});
}
public void callSomeMethod() {
// Perform some more operations after database call is finished
}
如果你来自Node背景,那么这可能看起来很相似。将函数传递给getUserFromEmail
public void otherMethod() {
getUserFromEmail("steve@example.com", new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Perform some more operations after database call is finished
}
@Override
public void onCancelled(FirebaseError firebaseError) {
System.out.println(firebaseError.getMessage());
}
});
}
public void getUserFromEmail(String email, ValueEventListener listener) {
rootRef.child("users")
.orderByKey()
.equalTo(email)
.addListenerForSingleValueEvent(listener);
}
答案 1 :(得分:0)
如果您真的想使用锁,可以控制流程。例如,使用CountdownLatch:
public DataSnapshot getUserFromEmail(String email) throws InterruptedException {
AtomicReference<DataSnapshot> dataSnapshotRef = new AtomicReference<DataSnapshot>();
CountDownLatch completeSignal = new CountDownLatch(1);
Firebase usersRef = rootRef.child("users");
//Asynchronous database call, want to stop everything else
usersRef.orderByKey().equalTo(email).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshotRef.set(dataSnapshot);
// Causes execution of the waiting thread to continue
// from the `await` call
completeSignal.countDown();
}
@Override
public void onCancelled(FirebaseError firebaseError) {
completeSignal.countDown();
}
});
// Execution on this thread pauses at the `await` call until
// countDown has been called from another thread.
completeSignal.await();
// Do stuff after onDataChanged or onCancelled has been called
DataSnapshot dataSnapshot = dataSnapshotRef.get();
}
但是,在Firebase返回一些数据之前,此方法将阻止执行getUserFromEmail
的线程。特别是,如果从UI线程调用getUserFromEmail
,则会阻止UI线程并导致ANR。
最好像这样遵循回调方法:
public DataSnapshot getUserFromEmail(String email, ValueEventListener listener) {
Firebase usersRef = rootRef.child("users");
//Asynchronous database call, want to stop everything else
usersRef.orderByKey().equalTo(email).addListenerForSingleValueEvent(listener);
}
public void getUserAndThenDoSomething() {
getUserFromEmail("bob@example.com", new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Do stuff after getting the email here
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}