2017-01-29 9 views
1

私はFirebaseを初めて使い、すべてのタスクが非同期的に呼び出されるという事実に多くの問題があります。Firebase - Android - fetchProvidersForEmail - なぜすべてのコールが非同期ですか?

たとえば、私はfetchProvidersForEmailを使用して、ユーザにサインアップまたはログインを指示する必要があるかどうかを確認しようとしています。しかし、タスクが終了するまでには、それは遅すぎます。

明らかかどうかはわかりませんが、私の現在のコード(動作しています)は以下のとおりです。私はそれをどのようにすることができますか?

public static void printProviders(String email) { 
    FirebaseAuth auth = FirebaseAuth.getInstance(); 
    auth.fetchProvidersForEmail(email).addOnCompleteListener(new OnCompleteListener<ProviderQueryResult>() { 
      @Override 
      public void onComplete(@NonNull Task<ProviderQueryResult> task) { 
       Log.d(TAG, "We have " + task.getResult().getProviders().size() + " results."); 
       for (int i = 0; i < task.getResult().getProviders().size(); i++) { 
        Log.d(TAG, "Provider " + (i+1) + ": " + task.getResult().getProviders().get(i)); 
       } 
      } 
     } 
    ); 
} 

ここで私は(もちろん、これは動作しません)を作成したいと思う方法の擬似コードがある...

public static boolean emailIsRegistered(String email) { 
    FirebaseAuth auth = FirebaseAuth.getInstance(); 
    auth.fetchProvidersForEmail(email).addOnCompleteListener(new OnCompleteListener<ProviderQueryResult>() { 
     @Override 
     public void onComplete(@NonNull Task<ProviderQueryResult> task) { 
      if (task.getResult().getProviders().size() > 0) { 
       return true; 
      } 
      return false; 
     } 
    }); 
} 

しかし、これは動作しませんので、リターン文はonComplete()のために無効であり、タスクは非同期に実行されるため...

これは初めてのことです。私はStackOverflowを通して検索しようとしましたが、私を助けたものは何も見つかりませんでした。うまくいけば誰かが助けることができる。

ありがとうございました!

答えて

4

fetchProvidersForEmailに電話すると、その情報はアプリのAPKで利用できません。 Firebaseクライアントは、この情報を取得するためにサーバにコールアウトする必要があります。

インターネットの性質上、結果がそれらのサーバーから戻ってくるまでには、不確定な時間がかかることを意味します。データが利用可能になるまで

  • を実行し、データが
  • 利用可能になったとき、あなたをコールバック続ける

    1. 待ち:

      クライアントはその間に何をすべきかについて、いくつかのオプションがありますデータを待つことは、コードが単純なままであることを意味します。しかし、それはまた、データが参照されている間あなたのアプリがブロックされていることを意味します。したがって、スピナーアニメーションは実行されず、ユーザーは他のことをすることはできません(あなたのアプリはうまくいくかもしれませんが、他者はできません)。これは悪いユーザーエクスペリエンスとみなされます。実際には悪いので、そのAndroid will show an Application Not Responding dialog if your app is in this state for 5 seconds

      代わりに、Firebase SDKは他のオプションを選択します。つまり、サーバーからデータを取得している間にコードを続行できます。次に、データが取得されると、ユーザーは指定したコードブロックにコールバックします。現代のWeb APIのほとんどはこのように構築されているので、すぐに手に入るようになればなるほど、すぐにそれらのAPIを効率的に使用することができます。

      私が非同期プログラミングを把握する最も簡単な方法は、問題を再構成することです。今、あなたは「電子メールがすでに使用されているかどうかを最初に判断し、ユーザーにサインインまたはサインインする」ことを試みています。

      if (emailIsRegistered(email)) { 
          signInUser(email); 
      } 
      else { 
          signUpUser(email); 
      } 
      

      このアプローチは戻りブール、非同期メソッドを持つことは不可能である何かemailIsRegistered方法につながります。

      ここで問題を「電子メールがすでに使用されているかどうかを判断する」ように再設定しましょう。わかっている場合は、ユーザーをアップまたはサインインしてください。

      これは、コードの異なる部分につながる:

      public static boolean emailIsRegistered(String email) { 
      FirebaseAuth auth = FirebaseAuth.getInstance(); 
      auth.fetchProvidersForEmail(email).addOnCompleteListener(new OnCompleteListener<ProviderQueryResult>() { 
          @Override 
          public void onComplete(@NonNull Task<ProviderQueryResult> task) { 
           if (task.getResult().getProviders().size() > 0) { 
            signUserIn(email); 
           } 
           signUserUp(email); 
          } 
      }); 
      

      当社は、ユーザーのアップやemailIsRegistered方法で署名をしては結果が利用可能になったときに、その後を呼び出すための呼び出しを移動しました。

      ここで、これはもちろん、後続の動作をemailIsRegisteredメソッドにハードコードしているため、再利用することが難しくなります。そのため、これらの関数にコールバックが渡されることがよくあります。その素晴らしい例は、既に使用しているOnCompleteListenerです。 Firebaseクライアントがサーバーから結果を取得すると、渡されたonCompleteメソッドが呼び出されます。

      非同期呼び出しを処理することは難しく重要です。これがコンセプトの私の最善の説明であるかどうかは分かりません。

      :だから私は(私と他人の両方からの)いくつかの以前の説明が含まれます
    関連する問題