Quantcast
Channel: Recent Threads — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 204402

How to protect pages from premature Dispose() calls?

$
0
0

I have a Master-Detail application. The application has pages with UI controls, lists etc.

When user opens some page, it tries to load data from remote server. When remote server responds with authentication error, our application calls global error handler, which in turn detects the error and creates a new Login page and attaches it on Master.Detail to replace the current page.

At the very line where I replace Detail with new LoginPage (wrapped into NavigationPage, of course), I sometimes get an exception:

06-29 10:10:36.549 I/dalvikvm( 2220): android.runtime.JavaProxyThrowable: System.NotSupportedException: Unable to activate instance of type Xamarin.Forms.Platform.Android.PageRenderer from native handle 0xb5300021 (key_handle 0xa774d1a0). ---> System.MissingMethodException: No constructor found for Xamarin.Forms.Platform.Android.NavigationPageRenderer::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership) ---> Java.Interop.JavaLocationException: Exception of type 'Java.Interop.JavaLocationException' was thrown.

The problem does not occur always, and for unknown reason manifests itself only on Android 4.x devices and emulators. Newer Android devices seem to work fine.

While analyzing the reasons, I came to this one:
https://developer.xamarin.com/guides/android/under_the_hood/architecture/#Premature_Dispose_Calls

So, this seems to be the problem - when we replace Detail with new page, the old page is still being constructed, and then suddenly it gets discarded because we changed Detail, therefore something inside JNI starts disposing off objects and all hell breaks loose.

I found some related bugs:
https://bugzilla.xamarin.com/show_bug.cgi?id=40258

and also a workaround for NavigationPageRenderer here:
https://gist.github.com/SeeD-Seifer/ff8b522f7e8b55ec719f68e1765b0314

After this fix, I started getting occasional exceptions for ListViewRenderer, which I fixed the same way. But then I got the same exception for PageRenderer but when I tried the same kind of fix, my app started displaying blank page instead of normal page. At the and I got tired of this, because it seems no matter what I do, there always will be some Xamarin.Forms component which will suffer from being Disposed at wrong time during fast navigation between pages.

I tried to store global reference to current Detail before replacing it with a hope that it would prevent it from disposing for some time. Did not help. Then I thought that maybe I should somehow wait until current page has been fully loaded before replacing Detail, but I could not find any way to wait for Detail to become loaded (no events or properties to detect that).

There might also some race condition be going on because of awaits, although all Detail changes are being run from Device.BeginInvokeOnMainThread.

I'm just out of ideas.

I currently use Xamarin.Forms 2.3.2.127. I know that now there is 2.3.4.247 and I tried that, but it caused everything to fail miserably in my custom controls - something critical has been changed in Renderers and custom UI controls, which cause some thing be initiated in different order, thus causing some nullrefs here and there. I don't have time to fix them all, and I am not sure if the new 2.3.4.247 version is free of that Dispose issue, anyway.

So, what are my options here? How do I correctly avoid JNI Dispose() failures for cases when I replace master Detail while the page is still being loaded?


Viewing all articles
Browse latest Browse all 204402

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>