Xamarin Android OutOfMemoryError视图寻呼机中的大图像

时间:2016-04-27 14:16:22

标签: c# android xamarin android-viewpager out-of-memory

我有一个视图寻呼机,它以ImageView为背景。资源图像是750x1205,我将它们保存在drawable-xhdpi中。我没有任何其他尺寸的图像。

当我在某个时刻滚动寻呼机时,会抛出OutOfMemoryError

mPagerBackground.SetImageResource(page.backgroundResId);

我向AndroidManifest添加了android:largeHeap="true",我在我的适配器((BitmapDrawable)mPagerBackground.Drawable).Bitmap.Recycle();之前添加了SetImageResource,但是没有解决问题。

对于如何在不调整图像大小的情况下解决该问题,您有什么建议吗?

提前感谢您的帮助!

错误:

Java.Lang.OutOfMemoryError: 
  at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () [0x0000c] in /Users/builder/data/lanes/3053/a94a03b5/source/mono/external/referencesource/mscorlib/system/runtime/exceptionservices/exceptionservicescommon.cs:143
  at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue* parms) [0x00063] in /Users/builder/data/lanes/3053/a94a03b5/source/monodroid/src/Mono.Android/src/Runtime/JNIEnv.g.cs:571
  at Android.Widget.ImageView.SetImageResource (Int32 resId) [0x0005a] in /Users/builder/data/lanes/3053/a94a03b5/source/monodroid/src/Mono.Android/platforms/android-23/src/generated/Android.Widget.ImageView.cs:1350
  at [...](Android.Views.ViewGroup container, Int32 position) [0x0012c] in[...] Android.Support.V4.View.PagerAdapter.n_InstantiateItem_Landroid_view_ViewGroup_I (IntPtr jnienv, IntPtr native__this, IntPtr native_container, Int32 position) [0x00011] in <filename unknown>:0
  at at (wrapper dynamic-method) System.Object:9d522553-ebab-4c12-bb3c-1791ac15f74a (intptr,intptr,intptr,int)
  at --- End of managed exception stack trace ---
  at java.lang.OutOfMemoryError
  at at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
  at at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:587)
  at at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:422)
  at at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:840)
  at at android.content.res.Resources.loadDrawable(Resources.java:2110)
  at at android.content.res.Resources.getDrawable(Resources.java:700)
  at at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:323)
  at at android.support.v7.widget.TintManager.getDrawable(TintManager.java:175)
  at at android.support.v7.widget.TintManager.getDrawable(TintManager.java:168)
  at at android.support.v7.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:51)
  at at android.support.v7.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:72)
  at at md50e0099531e777fd8d5bed58953e4d813.EscapeLoungesPagerAdapter.n_instantiateItem(Native Method)
  at at md50e0099531e777fd8d5bed58953e4d813.EscapeLoungesPagerAdapter.instantiateItem(EscapeLoungesPagerAdapter.java:39)
  at at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:870)
  at at android.support.v4.view.ViewPager.populate(ViewPager.java:1086)
  at at android.support.v4.view.ViewPager.populate(ViewPager.java:952)
  at at android.support.v4.view.ViewPager$3.run(ViewPager.java:251)
  at at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:1849)
  at at android.support.v4.view.ViewPager.onInterceptTouchEvent(ViewPager.java:1978)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1859)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at md50e0099531e777fd8d5bed58953e4d813.ResideMenu.n_dispatchTouchEvent(Native Method)
  at at md50e0099531e777fd8d5bed58953e4d813.ResideMenu.dispatchTouchEvent(ResideMenu.java:61)
  at at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
  at at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
  at at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2068)
  at at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
  at at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
  at at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:60)
  at at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:60)
  at at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2016)
  at at android.view.View.dispatchPointerEvent(View.java:7886)
  at at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3954)
  at at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3833)
  at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
  at at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)
  at at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
  at at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3525)
  at at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)
  at at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3582)
  at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
  at at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)
  at at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
  at at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)
  at at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)
  at at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5602)
  at at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5582)
  at at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5553)
  at at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5682)
  at at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
  at at android.os.MessageQueue.nativePollOnce(Native Method)
  at at android.os.MessageQueue.next(MessageQueue.java:138)
  at at android.os.Looper.loop(Looper.java:123)
  at at android.app.ActivityThread.main(ActivityThread.java:5017)
  at at java.lang.reflect.Method.invokeNative(Native Method)
  at at java.lang.reflect.Method.invoke(Method.java:515)
  at at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
  at at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
  at at dalvik.system.NativeStart.main(Native Method)

修改

根据SushiHangover的建议,我尝试了下面的代码,但它没有帮助解决问题。

View view = (View) objectValue;
            ImageView imageView = (ImageView)view.FindViewById (Resource.Id.image_id);
            Drawable drawable = imageView.Drawable;
            if (drawable is BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable)drawable;
                if (bitmapDrawable != null) {
                    Bitmap bitmap = bitmapDrawable.Bitmap;
                    if (bitmap != null && !bitmap.IsRecycled) {
                        bitmap.Recycle();
                    }
                }
            }

            container.RemoveView(view);

看起来很有希望的是使用Picasso,但是视图寻呼机的图像加载速度非常慢。

2 个答案:

答案 0 :(得分:1)

1)你在C#中:使用.Dispose而不是.Recycle,但首先将imageView中的image属性设置为NULL(在图像上调用Dispose之前)。

2)然后强制垃圾收集器:Gc.Collect()

答案 1 :(得分:0)

完成使用后,您需要清理位图。 你应该这样做:

 public void Cleanup(Bitmap bitmap)
{
            if (bitmap == null)
                return;
            if (!bitmap.IsRecycled)
                bitmap.Recycle ();

            bitmap.Dispose ();
            bitmap = null;
}