[Bug] When running embedded the default renderers aren't using Fast Renderers
#8953 aperta il 18 dic 2019
Metriche repository
- Star
- (5644 stelle)
- Metriche merge PR
- (Nessuna PR mergiata in 30 g)
Descrizione
Description
Embedding needs to be fixed so that it uses Fast Renderers by default
Original Description
In our App we are seeing this error - not every time but often. It is a Xamarin.Android App that has a Xamarin.Forms Control embedded. If you navigate to another Xamarin.Forms Page and navigating back, this error can occur
This happens on Android only (so far i can test/reproduce it)
Error: cannot access a disposed object xamarin.forms.platform.android/Renderers/FrameRenderer.cs:115
CallStack:
Cannot access a disposed object. Object name: 'Android.Graphics.Bitmap'.
StackTrace: at Java.Interop.JniPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self) [0x00029] in <98bbbbcbc7484ff5a4c1b5515e7634fc>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeAbstractInt32Method (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x00000] in <98bbbbcbc7484ff5a4c1b5515e7634fc>:0 at Android.Graphics.Bitmap.get_Height () [0x0000a] in :0 at Xamarin.Forms.Platform.Android.FrameRenderer+FrameDrawable.Draw (Android.Graphics.Canvas canvas) [0x00043] in <8e6bfbbc42c1411bbf372065ebc4eeb9>:0 at Android.Graphics.Drawables.Drawable.n_Draw_Landroid_graphics_Canvas_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_canvas) [0x00011] in :0 at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.98(intptr,intptr,intptr)18.12.2019 09:33:28: Creating Async
Steps to Reproduce
Not so easy. i'm sorry i don't have a minimal app.
Expected Behavior
Actual Behavior
Basic Information
-
Version with issue: Xamarin Forms 4.3
-
Last known good version: Unknown; We saw this error once with 3.6 but with 4.3 very often - but not sure if it's the new Xamarin.Forms or changes in our code that changed the timing
-
IDE: VisualStudio 2019 16.3.10 / 16.4
-
Platform Target Frameworks:
- Android: 9.0 API Level 28- Pie
Analyses
The CallStack shows the problem in FrameRenderer line 115. The Problem is: __normalBitmap is disposed at this point (again: not every time but it can happen!)
The Fix
Before Line 115 add this If-Block:
if (_normalBitmap?.Handle == IntPtr.Zero) { _normalBitmap = null; }
So if the bitmap is disposed, just let the renderer create a new one.
Maybe the underlaying problem is somewhere else to be fixed but that was the place where we were able to see and fix it.
To workaround that in your own app
Create a new Class "FrameRendererEx.cs" and copy the complete FrameRenderer into it - with the new line i described above.
to use your own renderer: Add this to your MainActivity.cs `static void RegisterRenderer(Type handler, Type target) {
var types = typeof(Page).Assembly.GetTypes();
var registrar = types.First((t) => t.Name == "Registrar" && t.Namespace == "Xamarin.Forms.Internals");
var props = registrar.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
var property = props.First((p) => p.Name == "Registered");
object registered = property.GetValue(registrar);
var register = registered.GetType().GetMethod("Register", 0, new Type[] { typeof(Type), typeof(Type) });
register.Invoke(registered, new object[] { handler, target });
}`
And call it in the OnCreate like this (after an Xamarin.Forms.Forms.Init(...))
RegisterRenderer(typeof(Frame), typeof(FrameRendererEx));
If someone knows where to find the root cause of why the bitmap is disposed, let me know.
I would suggest the line described above (check the Handle of the bitmap) as a Bugfix to make the FrameRenderer more stable.
Thank you