Picasso: out of memory

后端 未结 4 1534
名媛妹妹
名媛妹妹 2020-12-08 14:34

I have a RecyclerView presenting several images using Picasso. After scrolling some time up and down the application runs out of memory with messag

相关标签:
4条回答
  • 2020-12-08 14:42

    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:

    • Set a fixed size for the ImageView
    • User a GlobalLayoutListener to get the ImageView's size once it is calculated and after this call Picasso adding the resize() method
    • Give Glide a try - its default configuration results in a lower footprint than Picasso (it stores the resized imaged rather than the original and uses RGB565)
    0 讨论(0)
  • 2020-12-08 14:43

    I 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
    
    }
    
    0 讨论(0)
  • 2020-12-08 15:01
    .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.

    0 讨论(0)
  • 2020-12-08 15:02

    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.

    0 讨论(0)
提交回复
热议问题