I'm getting the wrong image in a recycler view that shows images from the web.
My hypothesis is as follows:
let's say the recyclerview loads image A from the web into cell A' which is an ImageView using Picasso (or glide etc.)
Before the image is loaded, the user scrolls down, and cell A' scrolls out of the screen and is being recycled. Now it should show Image B that happens to be cached and therefore loads instantly from memory.
Then the web request for image A returns, and Picasso sets this image into ImageView A', overriding the correct image B
Am I missing something? How would you overcome this?
Related
I'm trying to replicate the functionality of Facebook's image upload. To briefly describe it you click the Photo button from the main screen of the app you are taken to an image picker that will let you select up to 30 images. Once selected the images load in some kind of list view that allows you to add a caption, remove the image from the list, or do some other Facebook-y things. If you scroll around the list can move very quickly, and if you only have 5-10 images you generally spend little to no time waiting for items to reload.
Right now I have a recycler view and am using Picasso to load the images from disk, resize them, and then display them. This works, but it's not smooth or fast. Even if I only have five or six images loaded they don't come up instantly if I scroll from the bottom back to the top. I have tried increasing the LRU Cache size in Picasso, but that didn't do anything at all. It seems like the scaled image isn't getting cached so it has to be scaled to fit the screen width every time. That's just my guess though.
Any suggestions on how to get this to run more smoothly?
I love Picasso and am using it for image caching in my app, where each list item has an image. The image is scaled correctly when shown, but when the user rotates their device, the image is the same old dimensions. However, when I scroll down and back up to the image, it is correct. How can I make the list refresh its images?
Currently I'm working with an application where one activity holds a list view with image and text for each row. I'm downloading the images using the volley. When the list view item is clicked the app will switch to a another activity with a detail view where a large version of the clicked image will show. For the both time I'm using NetworkImageView.
Images are loaded in the list view with caching. But the problem appeared on the detailed view. The images are showing from the previously loaded cache with low resolution. I want to load a good resolution image on detailed view which will cache the image separately for large view.
For the both screen image url are same. How to do that ?
Thanks in advance.
First thing is a bit obvious - make sure you images are at the wanted quality.
If that's the case, you'll probably want to load the image "manually" using the ImageLoader class, as the NetworkImageView by default, optimizes the size of the Bitmap it creates to be the size of the view itself. So what happens is, you first load the thumbnail view which is small, and the saved Bitmap is created in that size instead of the original image size. Then, when the bigger view requests the same image, the cached version is returned which is a small Bitmap, and the view scales it up, creating the low-res appearance.
Try using ImageLoader.get() with the width and height appropriate to the bigger view in the detail screen.
The other alternative is to load 2 versions of the same image.
I currently have a gridview that displays some thumbnail images. The problem I am running into is that when I scroll through the images I can see the images switch from old to new as they are being replaced. So, I was wondering how I would fix this. Is there a way to load images that aren't on the screen so when I scroll the user doesn't have to see the change in images?
The best way to avoid that effect is to set the image first to null in the getView() method of your adapter. You can then check an LRU cache if the image is already loaded. If yes, then set it right away, if not then load it asynchronous as a bitmap. Set it to the view and add it to the LRU cache.
I've reviewed some posts about lazy loading but I believe my problem is a bit different.
I have a gallery (my class extends Gallery) which displays 20 rather large in size images (400-500K each). I cannot load them all to gallery since I get an OutOfMemory exception.
So, I created an array of 20 Drawables and initially populated the first 9 elements (the images come from the Web) and set all the rest to null. My intention was this: on a fling to the right, fetch element no. 10 and set to null element no. 0. On another fling to the right fetch element no. 11 and set to null element no. 1 to null. Same logic on a fling left.
The problem is I can fling much faster than the elements are fetched.
My gallery has a BaseAdapter and its getView() looks something like this:
public View getView(int position, View convertView, ViewGroup parent){
ImageView imageView = new ImageView();
imageView.setDrawable(imageArray[position];
....
....
return imageView;
}
How do I tell getView() - if imageArray[position] is still null, show a "loading..." dialog and once it is set repeat yourself with the same position?
I don't want to see the imageView empty and then set on the fly. I want to not be able to see the imageView at all until it is set.
Thanks.
Gallery is designed for smooth experience. It will be very bad UI if you block the screen and don't switch to next image until it is fetched. This way user will not be able to fling at all. You should display some loading indicator instead of image while it is loading.
I think your scenario is rather common. You should download images and display them. If you get OutOfMemory you can try to supersample images Strange out of memory issue while loading an image to a Bitmap object.
If there's still OutOfMemory you should remove bitmaps from memory and cache them to SD. So when user flings back you can load images from SD again, it will be fast enough. And memory consumption will be lower. As you suggest you can have 10 most recent images cached in memory and others cached on SD.
You can take a look at my sample code Lazy load of images in ListView. Actually it's a ListView adapter but you can apply it to gallery with minor modifications. I think it will do exactly what you need.