I use Picasso to load images from app resources into ViewPager. Today I've faced the crash when I scroll ViewPager pages very fast. I recieved folowing error log:
08-13 13:10:33.968: ERROR/dalvikvm-heap(7896): Out of memory on a 1405456-byte allocation.
08-13 13:10:34.818: ERROR/dalvikvm(7896): can't open /data/misc/hprof_oom_dump.hprof: Permission denied
08-13 13:10:34.928: ERROR/Bitmap(7896): [FXN.ASD] Unable to create bitmap file. OutOfMemoryError.
java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:645)
at android.graphics.Bitmap.createBitmap(Bitmap.java:587)
at com.squareup.picasso.Picasso.transformResult(Picasso.java:479)
at com.squareup.picasso.Picasso.loadFromType(Picasso.java:401)
at com.squareup.picasso.Picasso.resolveRequest(Picasso.java:240)
at com.squareup.picasso.Picasso.run(Picasso.java:218)
at com.squareup.picasso.Request.run(Request.java:100)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:267)
08-13 13:10:34.998: ERROR/AndroidRuntime(7896): FATAL EXCEPTION: main
java.lang.RuntimeException: An unexpected exception occurred
at com.squareup.picasso.Request$1.run(Request.java:106)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4802)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:813)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:580)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at android.graphics.Bitmap.createBitmap(Bitmap.java:602)
at com.squareup.picasso.Picasso.transformResult(Picasso.java:479)
at com.squareup.picasso.Picasso.loadFromType(Picasso.java:401)
at com.squareup.picasso.Picasso.resolveRequest(Picasso.java:240)
at com.squareup.picasso.Picasso.run(Picasso.java:218)
at com.squareup.picasso.Request.run(Request.java:100)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
at java.lang.Thread.run(Thread.java:856)
at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:267)
08-13 13:10:35.228: ERROR/dalvikvm-heap(7896): Out of memory on a 3686416-byte allocation.
08-13 13:10:35.718: ERROR/wpa_supplicant(3206): ctrl_iface cmd = SIGNAL_POLL
08-13 13:10:36.188: ERROR/dalvikvm(7896): can't open /data/misc/hprof_oom_dump.hprof: Permission denied
08-13 13:10:36.298: ERROR/dalvikvm-heap(7896): Out of memory on a 3686416-byte allocation.
08-13 13:10:37.348: ERROR/dalvikvm-heap(7896): Out of memory on a 3686416-byte allocation.
08-13 13:10:38.278: ERROR/dalvikvm-heap(7896): Out of memory on a 3686416-byte allocation.
Here is code from my PagerAdapter where I load images:
@Override
public View instantiateItem(ViewGroup container, int position) {
View pagerItem = layoutInflater.inflate(R.layout.pager_item_wallpaper, container, false);
ImageView imgWallpaper = (ImageView) pagerItem.findViewById(R.id.wallpaper);
Picasso.with(context).load(wallpapers.get(position)).fit().into(imgWallpaper);
container.addView(pagerItem);
return pagerItem;
}
I use Picasso version 1.1.1.
Is something wrong with my code?
This isn't really a Picasso problem. You're telling it to load images and it is. The problem is that you're loading a ton of relatively large images and blowing your heap. We can't do anything about it. You need to optimize how the images are presented to ensure things like this don't happen. You might want to consider calling skipCache() so the images aren't kept in memory longer than they need to.
Thanks for the tip @JakeWharton You should put this kind of tips (Picasso features) in your documentation. Lot of people would be grateful ;-)
I have a similar problem with Picasso 2.3.3:
Out of memory on a 51121168-byte allocation.
"Picasso-/external/images/media/218" prio=5 tid=59 RUNNABLE
| group="main" sCount=0 dsCount=0 obj=0x42ef4e08 self=0x79ef7a28
| sysTid=2484 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=2048982144
| state=R schedstat=( 421674835 138577196 283 ) utm=40 stm=2 core=3
at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:703)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:679)
at com.squareup.picasso.ContentStreamBitmapHunter.decodeContentStream(ContentStreamBitmapHunter.java:60)
at com.squareup.picasso.ContentStreamBitmapHunter.decode(ContentStreamBitmapHunter.java:38)
at com.squareup.picasso.MediaStoreBitmapHunter.decode(MediaStoreBitmapHunter.java:55)
at com.squareup.picasso.BitmapHunter.hunt(BitmapHunter.java:144)
at com.squareup.picasso.BitmapHunter.run(BitmapHunter.java:101)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
at com.squareup.picasso.Utils$PicassoThread.run(Utils.java:394)
[ 07-28 10:36:22.818 1834: 2484 D/skia ]
--- decoder->decode returned false
I load the image like that:
ImageView pageView = newView(container, position);
mPicasso.load(mGalleryItems.get(position))
.placeholder(R.drawable.ic_gallery_empty)
.error(R.drawable.ic_gallery_error)
.fit()
.centerInside()
.skipMemoryCache()
.into(pageView);
I use "fit" to scale the image down to the ImageView size. The ImageView takes whole screen, which is quite big (Galaxy Note 3, 1080 x 1920), but the problem occurs when the system tries to allocate nearly 50 MB for a bitmap. It looks a little bit suspicious for me. According to my calculation, the bitmap should about about 8 MB.
Even if the scaling works OK, what else can I do to prevent such problems? Is it possible to limit the maximum loaded image size with Picasso, i.e. set somewhere that the image should be scaled down not to exceed e.g. 2 MB.
Hmm is this on Picasso 2.3.3? Can I have a sample app please?
Yes, 2.3.3.
https://drive.google.com/file/d/0B4ntcoZ-lp3VMUJZdTE5ZExiSWM/edit?usp=sharing
I wasn't able to receive a failure in that demo app, because it uses much less heap than my real app, but in the LogCat I saw
07-29 12:29:23.457 3237-3277/com.allegrogroup.test.piccassofail I/dalvikvm-heap﹕ Grow heap (frag case) to 75.700MB for 51121168-byte allocation
07-29 12:29:23.667 3237-3277/com.allegrogroup.test.piccassofail D/dalvikvm﹕ GC_FOR_ALLOC freed 6K, 7% free 74503K/79708K, paused 11ms, total 13ms
So it's also allocating 50 MB for each image.
The sampleSize calculated for this bitmap is 1 causing picasso to decode the whole bitmap.
reqWidth = 1080 <--- Your views width
reqHeight = 1776 <--- Your views height
height = 3096
width = 4128
I tried the sample size method from here also (http://developer.android.com/training/displaying-bitmaps/load-bitmap.html) and it seems to yield 1 as well.
Even if you managed to have a sampleSize of 2 then you would still be loading 12MB which of course is much much better than 50MB but huge none-the-less.
An inSampleSize of 2 would cause the dimens to be 2064 x 1548 which makes it smaller than your requested height so it uses inSampleSize of 1.
You are better off to use largeHeap=true if you are dealing with such big bitmaps or do custom decoding yourself to ensure no quality loss, or even update your view dimensions so you can at least decode less.
Thanks for the response :)
The use case I want to achieve is extremely simple: I want to display a full screen gallery of images (as in Android system Gallery). The requirements are as follows:
The first requirement is endangered on big screens, like the one in Note 3. You're right that there's no bug in Picasso, but I think that it'd be great to add a feature to help with this use case. Ideally, it'd be best to have something like
.maxImageDataSize(int bytes)
or at least
maxImageSize(int width, int height)
What do you think about it?
@Bersh how did you solve it?
@liuhuibin sorry too much time passed since that. But as i remember i finished with server-resized images. I mean that i server provided me with images with smaller size.
@Bersh Thank you all the same. :smile:
I have also seen this problem with Android 4.4.2 (no problem with Android 6).
I've managed to avoid the problem, using the resize method.
<=>
myPicassoInstance.load(imageUrl).resize(smallerWidth, smallerHeight).into(imageView, null);
I am also facing this issue, though image size is not very big. Did you able to resolve this. I can not fix the width and height.
Most helpful comment
This isn't really a Picasso problem. You're telling it to load images and it is. The problem is that you're loading a ton of relatively large images and blowing your heap. We can't do anything about it. You need to optimize how the images are presented to ensure things like this don't happen. You might want to consider calling
skipCache()so the images aren't kept in memory longer than they need to.