Java OutOfMemoryError uses Picasso images
I’m trying to load an image into an ImageView and get an OutOfMemoryError. Images are dynamically displayed based on a specific View in ViewPager. However, after I continued scrolling through ViewPager, the image ended up failing to load and resulting in an OutOfMemoryError.
Notice that I have 4 Views in ViewPager and the app seems to crash on View 2. I’m guessing the size of the image is too big, but I’m under the impression that Picasso will handle it accordingly:
Picasso code:
Picasso.with(getActivity())
.load(mImageURL)
.fit()
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_CACHE)
.into((ImageView) rootView.findViewById(R.id.comments_image));
XML
<ImageView
android:id="@+id/comments_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight=".525"
android:background="@color/black">
</ImageView>
Error
java.lang.OutOfMemoryError: Failed to allocate a 5074572 byte allocation with 132096 free bytes and 129KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:812)
at android.graphics.Bitmap.createBitmap(Bitmap.java:789)
at android.graphics.Bitmap.createBitmap(Bitmap.java:756)
at android.graphics.drawable.VectorDrawable$VectorDrawableState.createCachedBitmapIfNeeded(VectorDrawable.java:713)
at android.graphics.drawable.VectorDrawable.draw(VectorDrawable.java:280)
at com.squareup.picasso.PicassoDrawable.draw(PicassoDrawable.java:105)
at android.widget.ImageView.onDraw(ImageView.java:1176)
at android.view.View.draw(View.java:15231)
at android.view.View.updateDisplayListIfDirty(View.java:14167)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.draw(View.java:15234)
at android.view.View.updateDisplayListIfDirty(View.java:14167)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.support.design.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1131)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.draw(View.java:15234)
at android.support.v4.view.ViewPager.draw(ViewPager.java:2341)
at android.view.View.updateDisplayListIfDirty(View.java:14167)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.support.v4.widget.DrawerLayout.drawChild(DrawerLayout.java:1373)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.updateDisplayListIfDirty(View.java:14162)
at android.view.View.getDisplayList(View.java:14189)
at android.view.View.draw(View.java:14959)
at android.view.ViewGroup.drawChild(ViewGroup.java:3405)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3198)
at android.view.View.draw(View.java:15234)
at android.widget.FrameLayout.draw(F
Solution
I recommend that you use Glide because it is designed to work well by default on low-cost (and worst hardware) devices.
One big difference between Picasso and Glide is that the default format for Glide is RGB_565
while Picasso is ARGB_8888
. As you can see below, doing the same job, it saves 50% memory compared to Picasso.
However, if you don’t want to change your library, you can try using the .resize(int, int)
method to resize the image on Picasso’s builder.