[英]Asynchronous flow of execution in Java
我正在編寫一個方法,我想在其中查詢數據庫並在查詢完成后執行另一種方法。 但是,由於對數據庫的調用是異步的,我似乎無法弄清楚如何在數據庫調用完成之前停止主要執行流程,如下所示:
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 中是否有任何等效的方法來控制執行流程。 有什么簡單的方法可以實現我想做的事情嗎?
你不能停止主流程,主線程會繼續。 (除非您以其他方式停止它,但這會導致“應用程序無響應”,所以不要)。
只需在回調中執行操作即可。
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);
}
如果你真的想使用鎖,你可以控制流程。 例如使用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();
}
然而,這種方法會阻塞執行getUserFromEmail
的線程,直到 Firebase 返回一些數據。 特別是,如果您從 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) {
}
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.