I have a RecyclerView
presenting several images using Picasso
. After scrolling some time up and down the application runs out of memory with messag
I'm not sure fit()
works with android:adjustViewBounds="true"
. According to some of the past issues it seems to be problematic.
A few recommendations:
resize()
methodI just made a Singleton class to LoadImages. The problem was that I was using too many Picasso objects created with too many Picasso.Builder. Here's my implementation:
public class ImagesLoader {
private static ImagesLoader currentInstance = null;
private static Picasso currentPicassoInstance = null;
protected ImagesLoader(Context context) {
initPicassoInstance(context);
}
private void initPicassoInstance(Context context) {
Picasso.Builder builder = new Picasso.Builder(context);
builder.listener(new Picasso.Listener() {
@Override
public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
exception.printStackTrace();
}
});
currentPicassoInstance = builder.build();
}
public static ImagesLoader getInstance(Context context) {
if (currentInstance == null) {
currentInstance = new ImagesLoader(context);
}
return currentInstance;
}
public void loadImage(ImageToLoad loadingInfo) {
String imageUrl = loadingInfo.getUrl().trim();
ImageView destination = loadingInfo.getDestination();
if (imageUrl.isEmpty()) {
destination.setImageResource(loadingInfo.getErrorPlaceholderResourceId());
} else {
currentPicassoInstance
.load(imageUrl)
.placeholder(loadingInfo.getPlaceholderResourceId())
.error(loadingInfo.getErrorPlaceholderResourceId())
.into(destination);
}
}
}
Then you create an ImageToLoad
class that holds the ImageView, Url, Placeholder and Error Placeholder.
public class ImageToLoad {
private String url;
private ImageView destination;
private int placeholderResourceId;
private int errorPlaceholderResourceId;
//Getters and Setters
}
.memoryCache(new LruCache(100000000)) // Maybe something fishy here?
I would say this is indeed fishy - you're giving the LruCache
100MB of space. Although all devices are different, this is going to be at or above the limit for some devices, and keep in mind that this is only the LruCache
, not accounting for however much heap space the rest of your app requires. My guess is that this is the direct cause of the exception - you're telling the LruCache
that it's allowed to get much bigger than it should be.
I would reduce this to something like 5MB to first prove the theory, and then experiment with incrementally higher values on your target devices. You can also query the device for how much space it has and set this value programmatically if you like. Finally, there's the android:largeHeap="true"
attribute you can add to your manifest, but I've gathered this is generally bad practice.
Your images are indeed large so I would suggest reducing those as well. Keep in mind that even though you're trimming them, they still temporarily need to be loaded into memory at their full size.
with picasso you can solve the problem using its property like:
Picasso.with(context)
.load(url)
.resize(300,300)
.into(listHolder.imageview);
you need to resize the image.