sthewissen / Xamarin.Forms.PancakeView

An extended ContentView for Xamarin.Forms with rounded corners, borders, shadows and more!
MIT License
865 stars 107 forks source link

[Android] OutOfMemoryError - PancakeDrawable.draw #96

Open DECWebSites opened 4 years ago

DECWebSites commented 4 years ago

I'm using PancakeView 1.3.7 in the Xamarin Forms (android) project and I'm getting some crashes from devices using Android 6.0 and 7.0. The error is as follows:

JniEnvironment+StaticMethods.CallStaticObjectMethod (Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) Bitmap.CreateBitmap (System.Int32 width, System.Int32 height, Android.Graphics.Bitmap+Config config) PancakeDrawable.CreateBitmap (System.Boolean pressed, System.Int32 width, System.Int32 height) PancakeDrawable.Draw (Android.Graphics.Canvas canvas) Drawable.n_Draw_Landroid_graphics_Canvas_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_canvas) (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.45(intptr,intptr,intptr) java.lang.OutOfMemoryError: Failed to allocate a 785932 byte allocation with 380704 free bytes and 371KB until OOM dalvik.system.VMRuntime.newNonMovableArray(Native Method) android.graphics.Bitmap.nativeCreate(Native Method) android.graphics.Bitmap.createBitmap Bitmap.java:831 android.graphics.Bitmap.createBitmap Bitmap.java:808 android.graphics.Bitmap.createBitmap Bitmap.java:775 crc64f8908e42fa42e603.PancakeDrawable.n_draw(Native Method) crc64f8908e42fa42e603.PancakeDrawable.draw PancakeDrawable.java:41 android.view.View.getDrawableRenderNode View.java:16483 android.view.View.drawBackground View.java:16419 android.view.View.draw View.java:16229 android.view.View.updateDisplayListIfDirty View.java:15235 android.view.View.draw View.java:16008 android.view.ViewGroup.drawChild ViewGroup.java:3653 android.view.ViewGroup.dispatchDraw ViewGroup.java:3443 android.view.View.updateDisplayListIfDirty View.java:15230 android.view.View.draw View.java:16008 android.view.ViewGroup.drawChild ViewGroup.java:3653 android.support.v7.widget.RecyclerView.drawChild RecyclerView.java:4820 android.view.ViewGroup.dispatchDraw ViewGroup.java:3443 android.view.View.draw View.java:16241 android.support.v7.widget.RecyclerView.draw RecyclerView.java:4219 android.view.View.updateDisplayListIfDirty View.java:15235 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ViewGroup.recreateChildDisplayList ViewGroup.java:3637 android.view.ViewGroup.dispatchGetDisplayList ViewGroup.java:3617 android.view.View.updateDisplayListIfDirty View.java:15195 android.view.ThreadedRenderer.updateViewTreeDisplayList ThreadedRenderer.java:281 android.view.ThreadedRenderer.updateRootDisplayList ThreadedRenderer.java:287 android.view.ThreadedRenderer.draw ThreadedRenderer.java:322 android.view.ViewRootImpl.draw ViewRootImpl.java:2682 android.view.ViewRootImpl.performDraw ViewRootImpl.java:2496 android.view.ViewRootImpl.performTraversals ViewRootImpl.java:2125 android.view.ViewRootImpl.doTraversal ViewRootImpl.java:1140 android.view.ViewRootImpl$TraversalRunnable.run ViewRootImpl.java:6233 android.view.Choreographer$CallbackRecord.run Choreographer.java:858 android.view.Choreographer.doCallbacks Choreographer.java:670 android.view.Choreographer.doFrame Choreographer.java:606 android.view.Choreographer$FrameDisplayEventReceiver.run Choreographer.java:844 android.os.Handler.handleCallback Handler.java:739 android.os.Handler.dispatchMessage Handler.java:95 android.os.Looper.loop Looper.java:148 android.app.ActivityThread.main ActivityThread.java:5530 java.lang.reflect.Method.invoke(Native Method) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run ZygoteInit.java:733 com.android.internal.os.ZygoteInit.main ZygoteInit.java:623

What could it be?

JohamVan commented 4 years ago

Same issue. Any solution?

DECWebSites commented 4 years ago

Same issue. Any solution?

No (;

andrev121 commented 4 years ago

Seems to be, issue is related with memory leak. Every PancakeView object stays in memory forever. During app life-cycle soon or later all free memory will be used by PancakeView objects. After that OutOfMemory is thrown.

DECWebSites commented 4 years ago

And there is no solution?

andrev121 commented 4 years ago

And there is no solution?

The only serious solution is waiting till fixed this. As for me i decided return to simple frame and grid instead of pancake. That's might not be the case for you. Also you can try find pancake version which not contains memory issue.

DaviBittencourt commented 3 years ago

I am suffering from the same problem. I will make a backup of the app to remove the pancakeView from the project. But when the problem is solved, I think about reusing it, I really like it.

It is sad that there still no solution: /

sthewissen commented 3 years ago

I will personally not get around to fixing this, as I simply don't have the time anymore to do it. Other projects are taking up my time, which means this one is slowly falling below the radar. However, I'll gladly take PRs for a fix though.

DaviBittencourt commented 3 years ago

Below is a report of the crash that occurs with me.

It happens when the pancakeView is loaded numerous times, for example, a popup that is called several times in a data synchronization, or a button that changes color when a background task is being executed.

https://drive.google.com/file/d/1djFnIERUBGMTYYqk-zCy1oeGFIlgwu2O/view?usp=sharing

cabal95 commented 3 years ago

I don't know if this is the exact same problem people are running into in this issue, but we recently diagnosed a problem we were having that I think is probably at least related. If you use PancakeView with a BackgroundColor or a CornerRadius, it creates a new drawable to handle those things. The problem is, as devices have gotten larger that creates a memory issue.

We were testing on a Moto g7, which is 1080 pixels wide (it runs at like 3x ratio so the app only sees 340 pixels wide or whatever). So if we create a PancakeView to contain our content the drawable it creates is going to be roughly 1080 pixels wide. Lets assume, as in our case, that we had 7 screens worth of content in this PancakeView. That is roughly 14,000 pixels in height.

Now lets do some math on that. We have 14,000 x 1,080 x 4. Why x4? Because it's creating a 32-bit RGBA bitmap to draw the background into. Which means it's creating a 60MB bitmap every time it needs to redraw.

Because that bitmap is, as far as I can tell, an unmanaged resource, the garbage collector doesn't know anything about it. This means it isn't out of the realm of possibility that that you might have a few of these hanging around (in android heap) until the GC finally decides to collect your tiny little C# objects (views) that are holding a reference to these bitmaps.

Thus, Android runs out of memory.

As an aside, in our case we weren't running out of memory, but we were getting random crashes about a drawable being over 100MB. Visually, we were seeing weird things where images were not being rendered and scrolling on the page was extremely sluggish. As soon as we got rid of the absurdly sized PancakeView all those problems went away. (note: I'm not blaming PancakeView, when we talked about how we were using it we realized it was incredibly stupid on our part to use it for something so simple but massively oversized).

cassionishiguchi commented 2 years ago

I ran into this issue as well. Is this just a matter of calling base.Dispose(disposing) in PancakeViewRenderer's Dispose method?