2016-10-11 18 views
1

私はデータベースをクエリし、クエリが終了した後に別のメソッドを実行する方法を書いています。データベースへの呼び出しが非同期であるので、しかし、私は、データベース呼び出しが完了するまでそのように、実行の主な流れを停止する方法を見つけ出すように見えることはできません。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 
} 

私が働いに使用していますNodejの非同期コールバックを使用していますが、Javaで実行フローを制御する同等の方法があるかどうかはわかりません。私がしたいことを達成するための簡単な方法はありますか?

答えて

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 
} 

ノードの背景から来た場合、これは似たように見えるかもしれません。 getUserFromEmail

public void otherMethod() { 
    getUserFromEmail("[email protected]", 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); 
} 
+0

私はコールバックが行われた後、元のmeyhodから値を返すしたい場合はどう? – Matt

+1

メソッドは 'void'です。あなたは戻ることはできません。本当に、あなたはすべきではありません。非同期が 'return'ステートメントでうまく動かない –

+1

コールバック内の' dataSnapshot'から取得したデータから直接UIを更新することができます –

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("[email protected]", new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      // Do stuff after getting the email here 
     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 
     } 
    }); 
} 
+0

前回ANRの先頭にチェックしました。 http://stackoverflow.com/a/33204705/209103 –

+0

で私のアップデートを見てください。それをUIスレッドで実行する場合はyes、そうでない場合はnoを実行します。 UIスレッドからそのメソッドを使用することについて人々に警告するための回答に追加されました。 –

関連する問題