Question

I'm using Xamarin.Android

The issue I'm facing is the DalvikVM heap size produces an OutOfMemoryException when we use bitmaps.

I’ve implemented the IDisposable pattern to use of bitmaps

using (var bmp = ImageResizer.DecodeSampledBitmapFromResource (Resources,
    Resource.Drawable.exampleImage, Resources.DisplayMetrics.WidthPixels / 2, 
    (int)((Resources.DisplayMetrics.WidthPixels / 2) * _aspect)))
{
    _btnFoo.SetImageBitmap (bmp);
    bmp.Dispose ();
}

public static class ImageResizer
{
    public static int CalculateInSampleSize(BitmapFactory.Options options, 
        int reqWidth, int reqHeight)
    {
        // Raw height and width of image
        var height = (float)options.OutHeight;
        var width = (float)options.OutWidth;
        var inSampleSize = 1D;
        if (height > reqHeight || width > reqWidth)
        {
            inSampleSize = width > height
            ? height/reqHeight
            : width/reqWidth;
        }
        return (int) inSampleSize;
    }

    public static Bitmap DecodeSampledBitmapFromResource(Resources res, int resId, 
        int reqWidth, int reqHeight)
    {
        var options = new BitmapFactory.Options {
            InJustDecodeBounds = true,
        };

        using (var dispose = BitmapFactory.DecodeResource(res, resId, options)) {
        }

        options.InSampleSize = CalculateInSampleSize(options, reqWidth, reqHeight);
        options.InJustDecodeBounds = false;
        return BitmapFactory.DecodeResource(res, resId, options);
    }
}

Implementing this fix has helped with some of the issues however the app crashes only on a Galaxy S4 when the third bitmap is used which was happening before the above fix.

See below the stack trace for the crash.

I/dalvikvm-heap(  312): Clamp target GC heap from 132.902MB to 128.000MB
D/dalvikvm(  312): GC_FOR_ALLOC freed 1852K, 4% free 126271K/130904K, paused 25ms, total 25ms
I/dalvikvm-heap(  312): Forcing collection of SoftReferences for 3134212-byte allocation
I/dalvikvm-heap(  312): Clamp target GC heap from 132.894MB to 128.000MB
D/dalvikvm(  312): GC_BEFORE_OOM freed 10K, 4% free 126261K/130904K, paused 29ms, total 29ms
E/dalvikvm-heap(  312): Out of memory on a 3134212-byte allocation.
I/dalvikvm(  312): "main" prio=5 tid=1 RUNNABLE
I/dalvikvm(  312):   | group="main" sCount=0 dsCount=0 obj=0x413eeb38 self=0x413ddd78
I/dalvikvm(  312):   | sysTid=312 nice=0 sched=0/0 cgrp=apps handle=1074968028
I/dalvikvm(  312):   | state=R schedstat=( 0 0 0 ) utm=246 stm=59 core=2
I/dalvikvm(  312):   at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
I/dalvikvm(  312):   at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:596)
I/dalvikvm(  312):   at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
I/dalvikvm(  312):   at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:472)
I/dalvikvm(  312):   at guild.android.screens.CouponItemScreen.n_onTouch(Native Method)
I/dalvikvm(  312):   at guild.android.screens.CouponItemScreen.onTouch(CouponItemScreen.java:47)
I/dalvikvm(  312):   at android.view.View.dispatchTouchEvent(View.java:7495)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2291)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1985)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2291)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1985)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2291)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1985)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2291)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1985)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2291)
I/dalvikvm(  312):   at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1985)
I/dalvikvm(  312):   at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2240)
I/dalvikvm(  312):   at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1535)
I/dalvikvm(  312):   at android.app.Activity.dispatchTouchEvent(Activity.java:2466)
I/dalvikvm(  312):   at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2188)
I/dalvikvm(  312):   at android.view.View.dispatchPointerEvent(View.java:7689)
I/dalvikvm(  312):   at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3794)
I/dalvikvm(  312):   at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3678)
I/dalvikvm(  312):   at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4916)
I/dalvikvm(  312):   at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4895)
I/dalvikvm(  312):   at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4993)
I/dalvikvm(  312):   at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
I/dalvikvm(  312):   at android.os.MessageQueue.nativePollOnce(Native Method)
I/dalvikvm(  312):   at android.os.MessageQueue.next(MessageQueue.java:125)
I/dalvikvm(  312):   at android.os.Looper.loop(Looper.java:124)
I/dalvikvm(  312):   at android.app.ActivityThread.main(ActivityThread.java:5279)
I/dalvikvm(  312):   at java.lang.reflect.Method.invokeNative(Native Method)
I/dalvikvm(  312):   at java.lang.reflect.Method.invoke(Method.java:511)
I/dalvikvm(  312):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
I/dalvikvm(  312):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
I/dalvikvm(  312):   at dalvik.system.NativeStart.main(Native Method)
I/dalvikvm(  312):
D/skia    (  312): --- allocation failed for scaled bitmap
D/dalvikvm(15696): GC_CONCURRENT freed 2085K, 39% free 14681K/23884K, paused 2ms+13ms, total 40ms
Était-ce utile?

La solution

You just need to add this line to your manifest file. It will allocate the large memory for your application.

android:largeHeap="true"

Autres conseils

put in maifest file 

<application
    android:allowBackup="true"
    android:icon="@drawable/launch"
    android:label="@string/app_name"
    **android:largeHeap="true"** // <------ put this so that this exception wont come :)
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top