Firebase - Android - fetchProvidersForEmail - 为什么所有调用都是异步的?

时间:2017-01-29 07:01:35

标签: android firebase firebase-authentication

我是Firebase的新手,而且我在异步调用所有任务时遇到了很多问题。

例如,我正在尝试使用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搜索,但无法找到任何帮助我的东西。希望有人可以提供帮助。

谢谢!

1 个答案:

答案 0 :(得分:4)

当您致电fetchProvidersForEmail时,您的应用的APK中没有该信息。 Firebase客户端必须调用服务器才能获取此信息。

鉴于互联网的性质,这意味着在结果从这些服务器返回之前需要一段不确定的时间。

客户可以选择在此期间做什么:

  1. 等到数据可用
  2. 在数据可用时继续执行并回电
  3. 等待数据意味着您的代码保持简单。但这也意味着在查找数据时您的应用程序被阻止。所以:没有微调器动画会运行,用户不能做任何其他事情(这可能适用于您的应用程序,但不适用于其他人),等等。这被视为糟糕的用户体验。实际上很糟糕,Android will show an Application Not Responding dialog if your app is in this state for 5 seconds

    相反,Firebase SDK会选择其他选项:他们会让代码继续运行,同时他们会从服务器中检索数据。然后,当检索到数据时,它们会回调您提供的代码块。大多数现代Web API都是以这种方式构建的,因此您越早掌握它,就越能有效地使用这些API。

    我发现掌握异步编程的最简单方法是重构问题。现在,您正在尝试&#34;首先确定电子邮件是否已被使用,然后向上或在&#34;中签署用户。

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

    这种方法导致{em>返回布尔值的emailIsRegistered方法,这是异步方法无法实现的。

    现在让我们将问题重新设置为&#34;确定电子邮件是否已被使用。当我们知道这一点时,请在用户上签名或在&#34;中签名。

    这导致了不同的代码:

    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方法,然后在结果可用时调用。< / p>

    现在,这当然将后续操作硬编码到emailIsRegistered方法中,这使得重用更加困难。这就是为什么你经常看到回调被传递到这些函数中的原因。一个很好的例子就是您已经使用的OnCompleteListener。 Firebase客户端从服务器获取结果后,会调用您传入的onComplete方法。

    学习处理异步调用既困难又重要。我不确定这是否是我对这些概念的最佳解释。所以我将包括一些先前的解释(来自我和其他人):