Adeel Ahmad Adeel Ahmad - 22 days ago 10
Android Question

Picasso Library - Out of Memory

I am using Picasso library latest version 2.4.0 in my app for downloading and caching images. There are roughly 25-30 images of size 300KB-400KB each. I think that this is no way something big or heavy.

Even though the app is running fine, I'm getting out of memory allocations in my logcat. Can anyone explain why is this happening?

Code for loading images in GridView adapter:

Picasso.with(mContext).load(getUrl()).placeholder(R.drawable.placeholder)
.into(viewholder.image);


Here is my Logcat output:

I/dalvikvm-heap(11142): Grow heap (frag case) to 53.860MB for 2720016-byte allocation
I/dalvikvm-heap(11142): Forcing collection of SoftReferences for 3265936-byte allocation
E/dalvikvm-heap(11142): Out of memory on a 3265936-byte allocation.
I/dalvikvm(11142): "Picasso-/images/posters/34.71.jpg" prio=5 tid=18 RUNNABLE
I/dalvikvm(11142): | group="main" sCount=0 dsCount=0 obj=0x4283f248 self=0x60a47830
I/dalvikvm(11142): | sysTid=11196 nice=10 sched=0/0 cgrp=apps/bg_non_interactive I/dalvikvm(11142): | state=R schedstat=( 2070202497 1858185620 3947 ) utm=172 stm=35 core=3
I/dalvikvm(11142): at android.graphics.Bitmap.nativeCreate(Native Method)
I/dalvikvm(11142): at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
I/dalvikvm(11142): at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
I/dalvikvm(11142): at android.graphics.Bitmap.createBitmap(Bitmap.java:636)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.transformResult(BitmapHunter.I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:168)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:111)
I/dalvikvm(11142): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390I/dalvikvm(11142): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
I/dalvikvm(11142): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.I/dalvikvm(11142): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.I/dalvikvm(11142): at java.lang.Thread.run(Thread.java:841)
I/dalvikvm(11142): at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:408)
I/dalvikvm-heap(11142): Forcing collection of SoftReferences for 3265936-byte allocation
E/dalvikvm-heap(11142): Out of memory on a 3265936-byte allocation.
I/dalvikvm(11142): "Picasso-/images/posters/34.71.jpg" prio=5 tid=17 RUNNABLE
I/dalvikvm(11142): | group="main" sCount=0 dsCount=0 obj=0x42841b88 self=0x5ec91f90
I/dalvikvm(11142): | sysTid=11183 nice=10 sched=0/0 cgrp=apps/bg_non_interactive I/dalvikvm(11142): | state=R schedstat=( 2050467088 1713164574 3713 ) utm=172 stm=32 core=3
I/dalvikvm(11142): at android.graphics.Bitmap.nativeCreate(Native Method)
I/dalvikvm(11142): at android.graphics.Bitmap.createBitmap(Bitmap.java:726)
I/dalvikvm(11142): at android.graphics.Bitmap.createBitmap(Bitmap.java:703)
I/dalvikvm(11142): at android.graphics.Bitmap.createBitmap(Bitmap.java:636)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.transformResult(BitmapHunter.I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:168)
I/dalvikvm(11142): at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:111)
I/dalvikvm(11142): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:390I/dalvikvm(11142): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
I/dalvikvm(11142): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.I/dalvikvm(11142): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.I/dalvikvm(11142): at java.lang.Thread.run(Thread.java:841)
I/dalvikvm(11142): at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:408)

Answer

Your original code was downloading the full image, loading the full image into memory, then having Android scale the image down to fit your ImageView.

In this case, you do not need the full image in memory -- you need something closer in size to what the ImageView is.

fit() on Picasso handles this. It uses inSampleSize on BitmapFactory.Options to downsample the image as it is being loaded into memory, to get you something around the size of the ImageView, letting Android scale from there. This will significantly reduce the memory footprint of each image, particularly depending on how big of an ImageView you are using.

Comments