如何从 Android 上的 Firebase 存储正确下载多个文件?

Posted

技术标签:

【中文标题】如何从 Android 上的 Firebase 存储正确下载多个文件?【英文标题】:How properly download multiple files from Firebase Storage on Android? 【发布时间】:2018-08-12 21:23:01 【问题描述】:

我在 android 应用程序上从 Firebase Storage 下载文件时遇到问题。我知道如何下载一张图像并将其显示在ImageView 上的方法。但是当我需要在单个活动中下载多个图像时,我遇到了问题。 我在List<String> 中有文件的名称,例如:[img1, img2]

对于文件下载我写了一个方法:

private void downloadImg(String name) 
    String path = "images/"+name+".png";
    StorageReference ref = storage.getReference().child(path);
    try 
        final File localFile = File.createTempFile("Images", "png");
        ref.getFile(localFile).addOnSuccessListener(new OnSuccessListener< FileDownloadTask.TaskSnapshot >() 
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) 
                Bitmap bitmap = BitmapFactory.decodeFile(localFile.getAbsolutePath());
                if (bitmap != null) 
                    initImages(bitmap);
                
            
        ).addOnFailureListener(new OnFailureListener() 
            @Override
            public void onFailure(@NonNull Exception e) 
                Log.e(Tags.IMAGES, e.getMessage());
            
        );
     catch(IOException e) 
        Log.e(Tags.IMAGES, e.getMessage());
    
  

此方法下载一个 .png 文件,并将给定 name 作为参数并将其设置为新的ImageView

在 ImageView 上设置图片的方法:

不应该有问题
private void initImages(Bitmap bitmap) 
    int total = imageNames.size();
    int column = 4;
    ImageView image;
    for (int i = 0, c = 0, r = 0; i < total; i++, c++) 
        if (c == column) 
            c = 0;
            r++;
        
        image = new ImageView(this);
        image.setScaleType(ImageView.ScaleType.CENTER_CROP);
        image.setContentDescription(getString(R.string.addImageDescription));
        image.setBackgroundColor(getResources().getColor(R.color.bHint));
        image.setImageBitmap(bitmap);
        image.setOnClickListener(imageClickListener(bitmap));
        imagesGrid.addView(image, i);
        GridLayout.LayoutParams params = new GridLayout.LayoutParams();
        params.setGravity(Gravity.CENTER);
        params.height = hw_60;
        params.width = hw_60;
        params.setMargins(padding_5, padding_5, padding_5, padding_5);
        params.columnSpec = GridLayout.spec(c);
        params.rowSpec = GridLayout.spec(r);
        image.setLayoutParams(params);
    
  

此方法创建新的ImageView 并将下载的Bitmap 设置为它。 我在活动onCreate() 上使用downloadImg(name); 方法,如下所示:

for(String name : imageNames) 
    downloadImg(name);
  

总结和主要问题:

我的 Firebase 存储中有两个具有给定名称的对象 [img1, img2]。相同的文件名存储到List&lt;String&gt;,用于按名称获取文件。在活动中onCreate() 方法为每个名称调用downloadImg(name) 方法。该方法下载图像并将其设置为新的ImageView我的问题是只有一张图像会被下载并显示两次。我尝试了其他一些方法来获取名称从列表中下载文件。所以有时 img1 会同时出现在 ImageViews 上,有时 - img2。因为这个方法只出现了两次img1

ps:我已经搜索过此类问题的答案。没有可能的重复。

【问题讨论】:

在说重复之前,请阅读所有描述和主要问题。谢谢。 为什么你有一个带有 downloadImg() 的 for 循环,然后又有一个 initImages() 和另一个被多次调用的 for 循环? 我错过了。我只在图像下载方法上搜索问题。谢谢你。那是我的错。 【参考方案1】:

我也有类似的问题,localFile var 在 下载完成并且 onSuccess 想要使用它。 我最终做了这样的事情

ArrayMap<String, File> localTmpFileArray = new ArrayMap<String, File>();
...
private void populateAvailableImages() 

    populateImageView("firstImpression.jpg", R.id.image_edit_profile_first_impression);
    populateImageView("profileImage1.jpg", R.id.image_profile_1);
    populateImageView("profileImage2.jpg", R.id.image_profile_2);

private void populateImageView(final String serverSideImageName, final int
        imageViewResourceId) 

    File imageLocalTmpFile = null;

    try 
        imageLocalTmpFile = File.createTempFile(serverSideImageName, "jpg");
     catch (IOException e) 
        Log.w("ops", e);
        Toast.makeText(getApplicationContext(), "Could not create local file. Storage " +
                "full??", Toast.LENGTH_LONG).show();
    

    localTmpFileArray.put(serverSideImageName, imageLocalTmpFile);

    StorageReference storageRef;
    storageRef = FirebaseStorage.getInstance().getReference();
    StorageReference imageRef = storageRef.child("users/" + FauthUtils.getUserId() + "/" +
            serverSideImageName);
    imageRef.getFile(localTmpFileArray.get(serverSideImageName)).addOnSuccessListener(new OnSuccessListener<FileDownloadTask.TaskSnapshot>() 
        @Override
        public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) 
            ImageView imageView = (ImageView) findViewById(imageViewResourceId);
            imageView.setImageURI(Uri.fromFile(localTmpFileArray.get(serverSideImageName)));
        
    ).addOnFailureListener(new OnFailureListener() 
        @Override
        public void onFailure(@NonNull Exception exception) 
            // Handle failed download
            // ...
        
    );

【讨论】:

以上是关于如何从 Android 上的 Firebase 存储正确下载多个文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Android 上的 Firebase DataSnapshot 中提取对象列表

如何从 Android 上的 Firebase DataSnapshot 中提取对象列表

如何从 Android 应用程序中删除 Firebase 用户?

如何在 Android 上的 Firebase 存储中设置持久性?

我如何在Android应用上运行自动机器人测试?就像Firebase测试实验室上的那个]] << [

动态创建的 Firebase 动态链接不适用于 Android