仅在Firebase任务完成时完成AsyncTask

时间:2018-03-12 02:03:59

标签: android firebase android-asynctask firebase-storage

如何在另一个异步方法完成时才让AsyncTask的doInBackground()返回?

在较高的层面上,活动的目的是允许用户上传评论。评论也可能有图像。现在在我的代码中,我有两个AsyncTasks:ImageCompressionTaskImageUploadTask。基本上,一旦用户选择要上传的图像,就为每个图像执行ImageCompressionTask。在该任务的onPostExecute()方法中,执行ImageUploadTaskImageUploadTask的目的是上传压缩图像并使用上述上载图像的下载URL更新Firestore(数据库)。以下是其代码:

public class ImageUploadTask extends AsyncTask<byte[], Integer, Void> {

    @Override
    protected Void doInBackground(byte[]... bytes) {
        StorageReference ref = App.getFireStorage().getReference();
        ref = ref.child("review_images/" +
                mDestinationId + "/" +
                mExistingReview.getReviewId() + "/" +
                mUploadProgressCount);

        ref.putBytes(bytes[0]).addOnSuccessListener(taskSnapshot -> {
            String url = taskSnapshot.getDownloadUrl().toString();
            mExistingReview.getImages().add(url);

            App.getFirestore().collection("reviews").document(mExistingReview.getReviewId()).set(mExistingReview);

            mUploadProgressCount++;
        });

        return null;
    }
}

然而,问题是doInBackground()过早地返回。我理解为什么会发生这种情况(因为ref.putBytes()方法异步运行)但我希望它等到ref.putBytes()完成。我该怎么做?

3 个答案:

答案 0 :(得分:2)

请你这样检查一下:

 @Override
protected synchronized Void doInBackground(byte[]... bytes) {
    StorageReference ref = App.getFireStorage().getReference();
    ref = ref.child("review_images/" +
            mDestinationId + "/" +
            mExistingReview.getReviewId() + "/" +
            mUploadProgressCount);

    ref.putBytes(bytes[0]).addOnSuccessListener(taskSnapshot -> {
        String url = taskSnapshot.getDownloadUrl().toString();
        mExistingReview.getImages().add(url);

        App.getFirestore().collection("reviews").document(mExistingReview.getReviewId()).set(mExistingReview);

        mUploadProgressCount++;
    });

    return null;
}

答案 1 :(得分:1)

我用ObservableInteger

解决了这个问题

是一个侦听值的侦听器

private ObservableInteger mObsInt;

 //Listener
        mObsInt = new ObservableInteger();
        mObsInt.set(0);

        mObsInt.setOnIntegerChangeListener(new OnIntegerChangeListener()
        {
            @Override
            public void onIntegerChanged(int newValue)
            {
                if (mObsInt.get()==1)
                    Log.e("Downloads"," mObsInt 1");
                Log.e("Download1"," Finished first process ");
                if (mObsInt.get()==2){
                    Log.e("Downloads"," mObsInt 2");
                    Log.e("Download2"," Finished second process ");
                    mProgressDialog.dismiss();
                    Intent mainIntent = new Intent().setClass(LoginActivity.this, Principal.class);
                    startActivity(mainIntent);
                    finish();
                }
            }
        });

然后执行此操作(在进程完成或asynctask之后)

mObsInt.set(mObsInt.get()+1);

所以它会计数,如果第一个完成的黑暗将是1,当第二个完成时,黑暗将是2,所以在黑暗== 2之后,你可以继续进行你需要的其他活动或过程< / p>

快乐的编码!

答案 2 :(得分:1)

这可以通过CountDownLatch完成:

 public class ImageUploadTask extends AsyncTask<byte[], Integer, Void> {

            @Override
            protected Void doInBackground(byte[]... bytes) {

                // Initialize CountDownLatch
                final CountDownLatch signal = new CountDownLatch(1);

                StorageReference ref = App.getFireStorage().getReference();
                ref = ref.child("review_images/" +
                        mDestinationId + "/" +
                        mExistingReview.getReviewId() + "/" +
                        mUploadProgressCount);

                ref.putBytes(bytes[0]).addOnSuccessListener(taskSnapshot -> {
                    String url = taskSnapshot.getDownloadUrl().toString();
                    mExistingReview.getImages().add(url);

                    App.getFirestore().collection("reviews").document(mExistingReview.getReviewId()).set(mExistingReview);

                    mUploadProgressCount++;

                   // Start count down
                   signal.countDown();
                });

                // Wait for putBytes to return and handle case if
                // threads get interrupted.
                // You can also specify a maximum time to wait before 
                // displaying error to user (ie Try Again)
                try {
                    signal.await(30, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                return null;
            }
        }