【问题标题】:Java Thread waits forever on Async TaskJava 线程在异步任务上永远等待
【发布时间】:2016-06-07 11:42:54
【问题描述】:

createUserWithEmailAndPassword 返回的对象是Task<AuthResult>,我可以为其设置onSuccessonFailure 回调;但主要问题是,我需要这里的主线程 wait 完成此过程,然后再进行下一步。创建部分 工作,但是当线程最终完成时,Task 对象说成功为假并返回,这也让我感到困惑,因为它确实成功地创建了用户。

if (firebaseAuth.getCurrentUser() == null) {
    final Task<AuthResult> resultTask = firebaseAuth.createUserWithEmailAndPassword(
            "email@address.com",
            "tester1234");
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            while(!resultTask.isComplete()) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    thread.start();
    thread.join(10000);
    if(!resultTask.isSuccessful())
        return false;
}

在下面尝试这种方法只会无限期地挂起:

if (firebaseAuth.getCurrentUser() == null) {
    final CountDownLatch countDownLatch = new CountDownLatch(1);
    firebaseAuth.createUserWithEmailAndPassword(
            "email@address.com",
            "test1234")
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        countDownLatch.countDown();
                    }
                });
    countDownLatch.await();
}

【问题讨论】:

  • 你在哪里启动/执行你的任务?
  • 如果你不启动你的任务,它确实永远不会完成,有意义的 WDYT?
  • @NicolasFilotto 任务由createUserWithEmailAndPassword启动
  • 如果是这样,请向我们展示 createUserWithEmailAndPassword 的内容,因为到目前为止我们所拥有的没有帮助
  • @NicolasFilotto 这里是我没有深入研究 Firebase 代码developers.google.com/android/reference/com/google/firebase/…

标签: java multithreading android-asynctask firebase firebase-authentication


【解决方案1】:

我没有研究过 Firebase API,但是为了调试这个问题,我已经通过 API 了解了一下,即使我同意至少上面的 CountDownLatch 逻辑应该可以工作。

我看到有两个与任务完成相关的回调:

  1. public Task&lt;TResult&gt; addOnCompleteListener (OnCompleteListener&lt;TResult&gt; listener)
  2. public abstract Task&lt;TResult&gt; addOnSuccessListener (OnSuccessListener&lt;? super TResult&gt; listener)

还有一个回调 API 用于失败情况:

public abstract Task<TResult> addOnFailureListener (OnFailureListener listener)

所以此时,我的建议是使用所有三个回调来调试实际执行的回调:我们可以将代码更改为如下调试:

     firebaseAuth.createUserWithEmailAndPassword(
            "email@address.com",
            "test1234")
                .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        countDownLatch.countDown();
                    }
                }
                .addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                    @Override
                    public void onSuccess(TResult result) {
                        countDownLatch.countDown();
                    }
                }
                .addOnFailureListener(new OnFailureListener<AuthResult>() {
                    @Override
                    public void onFailure(Exception ex) {
                        countDownLatch.countDown();
                    }
                });

    countDownLatch.await();

所有的监听器都会在主应用线程上被调用。 此答案基于此link。如果对你有帮助,我会很高兴。谢谢。

【讨论】:

    【解决方案2】:

    解决方案是不阻塞主线程;仅当机制包装在 AsyncTask 或它自己的另一个线程中时,使用 CountDownLatch 或任何其他等待机制才可以。这最终意味着我要重写我的代码以使我的应用更具响应性。

    【讨论】:

      猜你喜欢
      • 2015-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-08
      • 2014-09-06
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      相关资源
      最近更新 更多