-4

Every time I load certain activity called ProductActivity, I encounter the following error:

Fatal Exception: java.lang.OutOfMemoryError: Failed to allocate a 15694612 byte allocation with 2874400 free bytes and 2MB until OOM
       at dalvik.system.VMRuntime.newNonMovableArray(VMRuntime.java)
       at android.graphics.BitmapFactory.nativeDecodeAsset(BitmapFactory.java)
       at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:613)
       at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:446)
       at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:988)
       at android.content.res.Resources.createFromResourceStream(Resources.java:2813)
       at android.content.res.Resources.loadDrawableForCookie(Resources.java:2514)
       at android.content.res.Resources.loadDrawable(Resources.java:2416)
       at android.content.res.MiuiResources.loadDrawable(MiuiResources.java:393)
       at android.content.res.TypedArray.getDrawable(TypedArray.java:751)
       at android.view.View.<init>(View.java:3740)
       at android.widget.ImageView.<init>(ImageView.java:139)
       at android.widget.ImageView.<init>(ImageView.java:135)
       at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:60)
       at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:56)
       at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:106)
       at android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1017)
       at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1076)
       at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:47)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:729)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:810)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:508)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:418)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
       at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:284)
       at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:143)
       at demand.inn.com.quflip.activity.ProductInfoActivity.onCreate(ProductInfoActivity.java:73)
       at android.app.Activity.performCreate(Activity.java:6041)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1109)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2283)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2392)
       at android.app.ActivityThread.access$800(ActivityThread.java:154)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:135)
       at android.app.ActivityThread.main(ActivityThread.java:5273)
       at java.lang.reflect.Method.invoke(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:372)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)

Now how should I optimize the resources so that I can get rid of this error?

Should I resize the images on the server or should I resize them inside my app to get free from all these. Currently, I am using picasso to load the images inside my app.

azizbekian
  • 60,783
  • 13
  • 169
  • 249
M thaker
  • 383
  • 1
  • 4
  • 15

2 Answers2

2

You are trying to load 15694612 bytes = 15 MB weigh image, which is too big. If there is no option to have a separate downsampled resource, then your option is to downsample it programmatically and then load it.

private Bitmap downscaleBitmapUsingDensities(final int sampleSize, final int imageResId) {
  final Options bitmapOptions = new Options();
  bitmapOptions.inDensity = sampleSize;
  bitmapOptions.inTargetDensity = 1;
  final Bitmap scaledBitmap = BitmapFactory.decodeResource(getResources(), imageResId, bitmapOptions);
  scaledBitmap.setDensity(Bitmap.DENSITY_NONE);
  return scaledBitmap;
}   

sampleSize is an integer which specifies how many times you want the source bitmap to be downsampled before loading it into memory.

Community
  • 1
  • 1
azizbekian
  • 60,783
  • 13
  • 169
  • 249
0

As you are using picasso to load the images, you can get the bitmap from the picasso by using following code:

Target target = new Target() {
            @Override
            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
           // do you compression logic here and apply that bitmap to image

            }

            @Override
            public void onBitmapFailed(Drawable errorDrawable) {

            }

            @Override
            public void onPrepareLoad(Drawable placeHolderDrawable) {

            }
        };


void foo() {
        Picasso.with(getContext()).load(getUrl()).into(target);
}

The answer provided by @azizbekian will give you scaled version of image, you can further compress it by using simple code mentioned in this link, which considers the orientation, aspect ration of image too.

Ichigo Kurosaki
  • 3,765
  • 8
  • 41
  • 56