Xamarin.forms: Object reference not set to an instance with Android.ShellSectionRenderer.UnhookEvents ()

Created on 24 Jun 2019  ·  20Comments  ·  Source: xamarin/Xamarin.Forms

Description

Object reference not set to an instance after clicking log out in MasterdetailPage(This is Shell). And then press the hardware back button of Android.

Steps to Reproduce

  1. Create ContentPage ->LoginPage
  2. Create MasterDetailPage -> This is the MasterPage

Expected Behavior

When login successfully Go to MasterPage(This is Shell) using App.Current.MainPage = MasterPage() and click log out will go to Login Page. I use App.Current.MainPage = Loginpage and then press the hardware back button of Android. It will terminate the app.

Actual Behavior

After Logout and press hardware back button of Android. Object reference not set to an instance shown.

Basic Information

Screenshots

Reproduction Link

shell 2 high in-progress Android bug

Most helpful comment

From the code and some tests, it's appear that the dispose of the shell components are completely broken 😱.
The shell renderer create components but don't track them after that, so they are never disposed (memory leak) !!!
There are mixed Dispose and OnDestroy method and ShellFlyoutRenderer doesn't have Dispose method at all.

@samhouts I can try to fix this, but I don't know well the code of the shell at this time.

@rpdomingo Until a fix is ​​made you can bypass the crash with the use of a custom renderer which dont null the shell in the dispose, like this.

[assembly: ExportRenderer(typeof(Shell), typeof(ShellRendererCustomDispose))]
namespace App.Droid.Renderers
{
    public class ShellRendererCustomDispose : ShellRenderer
    {
        bool _disposed;

        public ShellRendererCustomDispose(Context context)
            : base(context)
        {
        }

        protected override void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                Element.PropertyChanged -= OnElementPropertyChanged;
                Element.SizeChanged -= (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), this, "OnElementSizeChanged"); // OnElementSizeChanged is private, so use reflection
            }

            _disposed = true;
        }
    }
}

All 20 comments

@rpdomingo Can you please attach a small project that demonstrates this issue? Thanks!

@samhouts Thanks for the reply. Please clone my repo

https://github.com/rpdomingo/Xamarin.Forms.4.0

I've Tested in Xamain.Forms.4.0.0.425677 to 4.0.0.497661

I use API 23 android. Samsung S6.

Additional:
I've try normal contentpage as my masterpage and it works fine. There is a comment NormalContentPage in the repo.

Thank you

06-27 20:49:25.513 I/MonoDroid(27846): System.NullReferenceException: Object reference not set to an instance of an object. 06-27 20:49:25.513 I/MonoDroid(27846): at Xamarin.Forms.Platform.Android.ShellSectionRenderer.UnhookEvents () [0x00022] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\ShellSectionRenderer.cs:250 06-27 20:49:25.513 I/MonoDroid(27846): at Xamarin.Forms.Platform.Android.ShellSectionRenderer.OnDestroy () [0x00011] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\ShellSectionRenderer.cs:177 06-27 20:49:25.513 I/MonoDroid(27846): at Android.Support.V4.App.Fragment.n_OnDestroy (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <96541ba8a6104b52aadf4218488f978c>:0 06-27 20:49:25.513 I/MonoDroid(27846): at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.60(intptr,intptr)

@samhouts will wait this till resolved. Thank you :)

Thanks for the repro.
The NullReference is caused by the Shell which is null.
The Shell variable is the ShellRenderer and the only place where it is set to null is in the dispose method.
So the root cause is that the ShellRenderer is disposed before the ShellSectionRenderer, which is wrong.

@kvpt Thanks for the info. Hope this will resolved soon. 🙂

From the code and some tests, it's appear that the dispose of the shell components are completely broken 😱.
The shell renderer create components but don't track them after that, so they are never disposed (memory leak) !!!
There are mixed Dispose and OnDestroy method and ShellFlyoutRenderer doesn't have Dispose method at all.

@samhouts I can try to fix this, but I don't know well the code of the shell at this time.

@rpdomingo Until a fix is ​​made you can bypass the crash with the use of a custom renderer which dont null the shell in the dispose, like this.

[assembly: ExportRenderer(typeof(Shell), typeof(ShellRendererCustomDispose))]
namespace App.Droid.Renderers
{
    public class ShellRendererCustomDispose : ShellRenderer
    {
        bool _disposed;

        public ShellRendererCustomDispose(Context context)
            : base(context)
        {
        }

        protected override void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                Element.PropertyChanged -= OnElementPropertyChanged;
                Element.SizeChanged -= (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), this, "OnElementSizeChanged"); // OnElementSizeChanged is private, so use reflection
            }

            _disposed = true;
        }
    }
}

From #7435 I see it also happens when using split screen. Although it's probably the same cause because of the lifecycle events, it might be worth to explicitly test that scenario.

From the stacktrace the crash is issue from the OnDestroy.

09-08 18:34:00.933 I/MonoDroid( 7137): at Xamarin.Forms.Platform.Android.ShellSectionRenderer.UnhookEvents () [0x00022] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\ShellSectionRenderer.cs:254
09-08 18:34:00.933 I/MonoDroid( 7137): at Xamarin.Forms.Platform.Android.ShellSectionRenderer.OnDestroy () [0x00008] in D:\a\1\s\Xamarin.Forms.Platform.Android\Renderers\ShellSectionRenderer.cs:180

From the stacktrace the crash is trigerred by the component destroy event.
Which is already covered by the test case added in 6715.
Sadly it's a manual test only, because I can found a way to trigger a destroy without destroying the app, because in this case the test run end.

Just got this one on 4.2.0.815419. I am trying to launch a Uri with StartActivity.

Could I help You with this task?
It seems a very difficult one!

I have the same problem anyone found a way around?

I have the same problem anyone found a way around?

This worked for my app:
https://github.com/xamarin/Xamarin.Forms/issues/6640#issuecomment-506767739

perfect. tank's!

closed by #7768

So, is this resolved in 4.3? Sorry, can't determine from the logs...

@kvpt I added the above code to new class in my project, but, cannot build, get 2 errors on build now:

  • Error CS0234: The type or namespace name 'Shell' does not exist in the namespace 'App' (are you missing an assembly reference?) (CS0234) (Conference.Android)
  • Error CS0118: 'App' is a namespace but is used like a type (CS0118) (Conference.Android)

Maybe it's how I added this class? I copied code exactly as you have provided, and, named the class ShellRendererCustomDispose.cs in the root of my Android project.

@dbwelch Replace the namespace, App.Droid.Renderers in the example with the namespace of your app.

@kvpt Thanks, that makes sense. In the meantime, I replaced my Xamarin.Forms to 4.3.0.947036, and now I do not get the exception also! Will probably keep it.

Btw, my issue a little different, I received this error when I click on a notification that takes me back to the app, but, same exception as noted in this issue.

Thanks for the post!

Thanks for fixing this one 👍

Was this page helpful?
0 / 5 - 0 ratings