Java Thread在Async Task上永远等待

时间:2016-06-07 11:42:54

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

createUserWithEmailAndPassword返回的对象是Task<AuthResult>,我可以设置onSuccessonFailure回调。但主要问题是,我需要在这个过程中的主要线程 等待 才能完成,然后才能进入下一步。创建部分 正在工作,但是当线程最终完成时,Task对象表示成功为false并返回,这也让我感到困惑,因为它确实成功创建了一个用户。

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();
}

2 个答案:

答案 0 :(得分:0)

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

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

  1. public Task<TResult> addOnCompleteListener (OnCompleteListener<TResult> listener)
  2. public abstract Task<TResult> addOnSuccessListener (OnSuccessListener<? super TResult> listener)
  3. 一个回调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。我会很高兴,如果它对你有所帮助。感谢。

答案 1 :(得分:0)

解决这个问题的方法是不阻止主线程;如果机制包装在CountDownLatch或其自己的另一个线程中,则使用AsyncTask或任何其他等待机制是正常的。这最终意味着我可以重写我的代码,使我的应用程序更具响应性。