0

I want to download my images from Firebase Storage using RecyclerView . The last image is only appears and the other images are there but not appear on screen (Blank space instead of image) .

I made sure that the rest of images are appear individually .

Here is my model class .

public class ImageClass {


    private Bitmap bitmap;
    public ImageClass(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public void setBitmap(Bitmap bitmap) {
        this.bitmap = bitmap;
    }

}

My adapter

  ...
@Override
public myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_layout,parent,false);
    myViewHolder myViewHolder = new myViewHolder(row);
    return myViewHolder;
}


      @Override
public void onBindViewHolder(myViewHolder holder, int position) {
    ImageClass imageClass = myClassImageList.get(position);
        holder.imageView.setImageBitmap(imageClass.getBitmap());
}
 ...

my Main Activity

 imageNames.add(0,"ha.jpg");
    imageNames.add(1,"ahmed.jpg");

getData();
    adapter = new ImageRecyclerAdapter(imageClassList);
    recyclerView.setAdapter(adapter);
  }
   public void getData() {
    for(int i=0;i<imageNames.size();i++) {
        StorageReference ref = storageReference.child("filee/"+imageNames.get(i));
        try {
            localFile = File.createTempFile("Images", "jpg");
        } catch(IOException e) {
        }
        ref.getFile(localFile).addOnSuccessListener(new OnSuccessListener< FileDownloadTask.TaskSnapshot >() {
            @Override
            public void onSuccess(FileDownloadTask.TaskSnapshot taskSnapshot) {
                bitmap = BitmapFactory.decodeFile(localFile.getAbsolutePath());
                ImageClass imageClass = new ImageClass(bitmap);
                imageClass.setBitmap(bitmap);
                imageClassList.add( imageClass);
                recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));

                Toast.makeText(MainActivity.this, "Downloaded", Toast.LENGTH_SHORT).show();

            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(MainActivity.this, "NotDownloaded", Toast.LENGTH_SHORT).show(); 
            }
        });
    }
}
Ahmed
  • 259
  • 3
  • 14
  • This is not a good way to retrieve all the documents within your `filee` folder. Please take a look **[here](https://stackoverflow.com/questions/51455018/retrieving-documents-from-firebase/51455302)**. – Alex Mamo Jul 24 '18 at 14:32
  • When I add the URLs to a `Realtime database` ,what is the next step ? – Ahmed Jul 24 '18 at 14:39
  • Just query the node where you are storing the urls and display them in your RecyclerView, right? – Alex Mamo Jul 24 '18 at 14:41
  • Sorry I'm new in Firebase and my English isn't well , can you explain more what do you mean of "Just query the node " ? :) – Ahmed Jul 24 '18 at 14:44
  • 1
    If you are storing the urs in the Firebase database under a node, let's say `urls`, then you just need to get all the elements beneath that node, which are urls and display then in in your RecyclerView, is it ok now? – Alex Mamo Jul 24 '18 at 14:52

2 Answers2

3

Perhaps I would download the images in a Service, but talking about your current implementation, remember that getFile runs asynchronously, and also, where do you have bitmap declared? From what I can see that Object is being overwritten over and over again and then the reference from that object is being passed as a parameter in your ImageClass object.

One option could be to first create the ImageClass collection (e.g. Arraylist), Loop though them and save the Bitmaps.

So you ImageClass would be something like:

public class ImageClass {

    private Bitmap bitmap;
    //...
    private String name;

    public void setName(String name){
        this.name=name;
    }
    public String getName(){
        return this.name;
    }
}

And then something like this:

for(int i=0;i<images.size();i++) {
    ImageClass image = images.get(i);
    StorageReference ref = storageReference.child("filee/"+image.getName());
    //https://firebase.google.com/docs/storage/android/download-files#download_in_memory
    ref.getBytes(ONE_MEGABYTE).addOnSuccessListener(new OnSuccessListener<byte[]>() {
        @Override
        public void onSuccess(byte[] bytes) {
            image.setBitMap(BitmapFactory.decodeByteArray(bytes, 0, bytes.length));
            recyclerView.getAdapter().notifyItemChanged(images.indexOf(image));
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception exception) {            
            Toast.makeText(MainActivity.this, "NotDownloaded", Toast.LENGTH_SHORT).show(); //would not recomend this either
        }
    });
}

Be sure to checkout Firebase Storage quickstarts: https://github.com/firebase/quickstart-android/tree/master/storage

memogarrido
  • 323
  • 1
  • 7
  • what is the value of `ONE_MEGABYTE` should be ? – Ahmed Jul 24 '18 at 15:02
  • The maximum allowed size in bytes that will be allocated (maximum size to something you know your app can handle) see https://firebase.google.com/docs/reference/android/com/google/firebase/storage/StorageReference.html#getBytes(long) and https://firebase.google.com/docs/storage/android/download-files#download_in_memory – memogarrido Jul 24 '18 at 15:07
  • It works thank you . I want to know what are the 2 lines in `onSuccess` do ? – Ahmed Jul 24 '18 at 15:16
  • Perfect! The first line is just putting the Bitmap into your image object decodeByteArray creates a Bitmap from a byte array source https://developer.android.com/reference/android/graphics/BitmapFactory#decodeByteArray(byte[],%20int,%20int) And the second line is to update your layout, your RecyclerView, we are notifying some data changed (the bitmap) – memogarrido Jul 24 '18 at 15:22
  • Do you know how can I download images from `Firebase storage` which I uploaded it manually using`upload` button in `Firebase console` . I searched on it many times but I didn't find anything useful . – Ahmed Jul 24 '18 at 15:33
  • I don't think you can, take a look at: https://stackoverflow.com/a/37337436/1537389 – memogarrido Jul 24 '18 at 15:44
  • Aha every time I ended my search with this link . Thank you for your help – Ahmed Jul 24 '18 at 15:48
  • Although down there there is a possible solution using Cloud Functions, from what I can see you need to work around getting those files names into a database – memogarrido Jul 24 '18 at 15:50
  • Yes I have to get their names to loop in. – Ahmed Jul 24 '18 at 15:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/176700/discussion-between-ahmed-and-memogarrido). – Ahmed Jul 25 '18 at 08:57
0

My guess is that your download method is failing at big images. If you are using Firebase, you should take advantage of all the tools provided by it and implement a simpler and efficient solution already provided by Firebase UI. Basically, it uses a library named Glide which simplifies a lot what you are trying to achieve.

Rodrigo Mata
  • 1,779
  • 2
  • 14
  • 23