【问题标题】:Upload Multiple images and wait for completion before returning, android and firebase上传多张图片并等待完成后再返回,android和firebase
【发布时间】:2018-08-22 00:17:04
【问题描述】:

您好,我正在尝试上传多张图片,等待它们返回,将下载的 uri 编译成一个对象并将其发送回我的活动。我将其用作上传的参考,firebase。到目前为止我有这个

 private void saveStepWithImages(@NonNull Step step, Callback callback){

    if(step.getStepId() == null){
       Collection<Image> images =  step.getImages().values();

        List<Task<Uri>> taskArrayList= new ArrayList<>();
        for (Image i: images) {
            taskArrayList.add(uploadImageTask(new ImageUtils().StringToBitMap(i.getImageUrl()), i.getImageReference()));
        }

        Tasks.whenAll(taskArrayList).addOnCompleteListener(task -> {
            Uri downloadUri = task.getResult(); // throws an error because task.getResult is void
        });

    }else{
        updateStepInFirebase(step, callback);
    }

}

在我上传的图片中

private Task<Uri> uploadImageTask(final Bitmap bitmap, String prepend){
    final StorageReference ref = mStorageRef.child( prepend );

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
    byte[] data = baos.toByteArray();

    UploadTask uploadTask = ref.putBytes(data);
    bitmap.recycle();

    return uploadTask.continueWithTask(task -> {
        bitmap.recycle();
        return ref.getDownloadUrl();
    });
}

Step 是我创建的一个自定义对象,它包含一个图像映射,其中一个字符串作为键,值是一个图像。我的图像类看起来像这样

public class Image implements Parcelable {

    private String imageUrl;
    private String imageReference;


    public void Image(){

    }

    //Setters and getters here;
}

任何建议将不胜感激。谢谢!

【问题讨论】:

  • 您是否尝试过使用 Tasks 的 whenAllSuccess() 方法而不是 whenAll()
  • 我刚试了一下,可以得到所有的网址!非常感谢!

标签: android firebase task firebase-storage


【解决方案1】:

解决这个问题的关键是使用Tasks的whenAllSuccess()方法:

当所有指定的任务成功完成时,返回一个包含任务结果列表的任务。

Insted of Tasks 的whenAll() 方法:

当所有指定的任务都成功完成时,返回一个成功完成的任务。

请查看更多关于Tasks类的信息。

【讨论】:

    【解决方案2】:

    您可以通过将所有调用嵌套在一个数组中并将每个调用添加到firebase的Task API来将多个文件上传到firebase:

    定义引用和任务数组

    StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
    
    List<Task> myTasks = new ArrayList<>();
    

    在这个例子中,我使用了一个包含每个文件及其相应存储目标的映射

        for (Map.Entry<String, Attachment> entry : storageRouteMap.entrySet()) {
    
            String path = entry.getKey();
    
            final Attachment localAtt = entry.getValue();
            Uri fileUri = localAtt.getMyUri();
    

    我会将每个任务放在任务数组中,对于一个文件我有三个任务,一个用于上传文件,一个用于获取存储的 url,另一个用于将元数据写入实时数据库。

            final StorageReference ref = mStorageRef.child(path);
            ThreadPerTaskExecutor executor = new ThreadPerTaskExecutor();
            UploadTask t1 = ref.putFile(fileUri);
    
            myTasks.add(t1);
    
            Task<Uri> t2 = t1.continueWithTask(executor,new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
                @Override
                public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
                    if (!task.isSuccessful()) {
                        throw task.getException();
                    }
    
                    return ref.getDownloadUrl();
                }
            });
    
            myTasks.add(t2);
    
            Task<Void> t3 = t2.continueWithTask(executor,new Continuation<Uri, Task<Void>>() {
                @Override
                public Task<Void> then(@NonNull Task<Uri> task) throws Exception {
                    if (!task.isSuccessful()) {
                        throw task.getException();
                    }
    
                    Attachment uploadAtt = new Attachment();
                    uploadAtt.name = localAtt.name;
                    uploadAtt.url = task.getResult().toString();
                    uploadAtt.type = localAtt.type;
                    String idAtt = UtilFirebase.getAttachmentReference().push().getKey();
    
                    UtilLog.LogToConsole(TAG," => "+postId+" => "+uidAuthor+" =>"+idAtt);
    
                    return UtilFirebase.getAttachmentReference()
                            .child(postId)
                            .child(uidAuthor)
                            .child(idAtt)
                            .setValue(uploadAtt);
    
                }
            }).continueWith(executor,new VideoTransaction(communityId,localAtt.size,localAtt.type));
    
            myTasks.add(t3);
        }
    

    最后我会查看所有任务是否已完成或是否有错误,无论哪种方式,这都会将结果传达给主线程。

        Task finish = Tasks.whenAll((Collection) myTasks);
    
        finish.addOnCompleteListener(new ThreadPerTaskExecutor(), new OnCompleteListener() {
            @Override
            public void onComplete(@NonNull Task task) {
                if (task.isSuccessful()) {
                    callback.onComplete();
                } else {
                    callback.onError(task.getException().toString());
                }
            }
        });
    

    【讨论】:

      猜你喜欢
      • 2019-10-16
      • 2018-12-21
      • 2013-03-22
      • 2017-06-29
      • 1970-01-01
      • 2021-04-28
      • 2015-10-03
      • 2020-08-14
      相关资源
      最近更新 更多