[Android] Fix old root page dispose when main page change (#4707) Fixes #4706 Fixes...
authorKevin Petit <kevin.petit@outlook.com>
Fri, 22 Mar 2019 12:10:04 +0000 (13:10 +0100)
committerRui Marinho <me@ruimarinho.net>
Fri, 22 Mar 2019 12:10:04 +0000 (12:10 +0000)
* Android - Fix old root page dispose when main page change.

* Revert dead code cleanup.

* Use direct cast for IApplicationController

Co-Authored-By: kvpt <kevin.petit@outlook.com>
* Use direct cast for IApplicationController (bis).

* Unsubscribe the event handler on the right application object.

* Prevent disruptive layout request from toolbar + Revert renderer clearing modification.

* If the page change, do nothing (dont dispose).

* Unsubscribe activity from application on destroy.

* Paused activity must not react to application changes

* Use nameof.

Xamarin.Forms.Platform.Android/AppCompat/FormsAppCompatActivity.cs
Xamarin.Forms.Platform.Android/AppCompat/NavigationPageRenderer.cs
Xamarin.Forms.Platform.Android/AppCompat/Platform.cs
Xamarin.Forms.Platform.Android/FormsApplicationActivity.cs
Xamarin.Forms.Platform.Android/Platform.cs

index cbb2514..6718e74 100644 (file)
@@ -18,7 +18,6 @@ using AToolbar = Android.Support.V7.Widget.Toolbar;
 using AColor = Android.Graphics.Color;
 using ARelativeLayout = Android.Widget.RelativeLayout;
 using Xamarin.Forms.Internals;
-using System.Threading.Tasks;
 
 #endregion
 
@@ -84,11 +83,11 @@ namespace Xamarin.Forms.Platform.Android
 
                protected void LoadApplication(Application application)
                {
-                       if(!_activityCreated)
+                       if (!_activityCreated)
                        {
-                           throw new InvalidOperationException("Activity OnCreate was not called prior to loading the application. Did you forget a base.OnCreate call?");
+                               throw new InvalidOperationException("Activity OnCreate was not called prior to loading the application. Did you forget a base.OnCreate call?");
                        }
-                       
+
                        if (!_renderersAdded)
                        {
                                RegisterHandlerForDefaultRenderer(typeof(NavigationPage), typeof(NavigationPageRenderer), typeof(NavigationRenderer));
@@ -114,8 +113,11 @@ namespace Xamarin.Forms.Platform.Android
                                _renderersAdded = true;
                        }
 
+                       if (_application != null)
+                               _application.PropertyChanged -= AppOnPropertyChanged;
+
                        _application = application ?? throw new ArgumentNullException(nameof(application));
-                       (application as IApplicationController)?.SetAppIndexingProvider(new AndroidAppIndexProvider(this));
+                       ((IApplicationController)application).SetAppIndexingProvider(new AndroidAppIndexProvider(this));
                        Xamarin.Forms.Application.SetCurrentApplication(application);
 
                        if (Xamarin.Forms.Application.Current.OnThisPlatform().GetWindowSoftInputModeAdjust() != WindowSoftInputModeAdjust.Unspecified)
@@ -125,16 +127,6 @@ namespace Xamarin.Forms.Platform.Android
 
                        application.PropertyChanged += AppOnPropertyChanged;
 
-                       if (application?.MainPage != null)
-                       {
-                               var iver = Android.Platform.GetRenderer(application.MainPage);
-                               if (iver != null)
-                               {
-                                       iver.Dispose();
-                                       application.MainPage.ClearValue(Android.Platform.RendererProperty);
-                               }
-                       }
-
                        SetMainPage();
                }
 
@@ -187,14 +179,18 @@ namespace Xamarin.Forms.Platform.Android
 
                        if (Forms.IsLollipopOrNewer)
                        {
-                               // Listen for the device going into power save mode so we can handle animations being disabled  
+                               // Listen for the device going into power save mode so we can handle animations being disabled
                                _powerSaveModeBroadcastReceiver = new PowerSaveModeBroadcastReceiver();
                        }
                }
 
                protected override void OnDestroy()
                {
+                       if (_application != null)
+                               _application.PropertyChanged -= AppOnPropertyChanged;
+
                        PopupManager.Unsubscribe(this);
+
                        Platform?.Dispose();
 
                        // call at the end to avoid race conditions with Platform dispose
@@ -295,7 +291,13 @@ namespace Xamarin.Forms.Platform.Android
 
                void AppOnPropertyChanged(object sender, PropertyChangedEventArgs args)
                {
-                       if (args.PropertyName == "MainPage")
+                       // Activity in pause must not react to application changes
+                       if (_currentState >= AndroidApplicationLifecycleState.OnPause)
+                       {
+                               return;
+                       }
+
+                       if (args.PropertyName == nameof(_application.MainPage))
                                InternalSetPage(_application.MainPage);
                        if (args.PropertyName == PlatformConfiguration.AndroidSpecific.Application.WindowSoftInputModeAdjustProperty.PropertyName)
                                SetSoftInputMode();
@@ -326,7 +328,7 @@ namespace Xamarin.Forms.Platform.Android
                        PopupManager.ResetBusyCount(this);
 
                        Platform = new AppCompat.Platform(this);
-                       
+
                        Platform.SetPage(page);
                        _layout.AddView(Platform);
                        _layout.BringToFront();
index 2dcaa52..4c4ac2f 100644 (file)
@@ -18,7 +18,6 @@ using Android.Views;
 using Xamarin.Forms.Internals;
 using ActionBarDrawerToggle = Android.Support.V7.App.ActionBarDrawerToggle;
 using AView = Android.Views.View;
-using AColor = Android.Graphics.Color;
 using AToolbar = Android.Support.V7.Widget.Toolbar;
 using Fragment = Android.Support.V4.App.Fragment;
 using FragmentManager = Android.Support.V4.App.FragmentManager;
@@ -133,8 +132,11 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
                        {
                                if (_toolbarVisible == value)
                                        return;
+
                                _toolbarVisible = value;
-                               RequestLayout();
+
+                               if (!IsLayoutRequested)
+                                       RequestLayout();
                        }
                }
 
index 8ebca28..85fd606 100644 (file)
@@ -6,7 +6,6 @@ using Android.Content;
 using Android.OS;
 using Android.Views;
 using Android.Views.Animations;
-using ARelativeLayout = Android.Widget.RelativeLayout;
 using AView = Android.Views.View;
 using Xamarin.Forms.Internals;
 
@@ -251,6 +250,11 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
 
                internal void SetPage(Page newRoot)
                {
+                       if (Page == newRoot)
+                       {
+                               return;
+                       }
+
                        if (Page != null)
                        {
                                foreach (var rootPage in _navModel.Roots)
@@ -285,7 +289,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
                        pageRenderer.View.ImportantForAccessibility = importantForAccessibility;
                        if (forceFocus)
                                pageRenderer.View.SendAccessibilityEvent(global::Android.Views.Accessibility.EventTypes.ViewFocused);
-                       
+
                }
 
                void SetPageInternal(Page newRoot)
index 1ff182d..27ee495 100644 (file)
@@ -1,7 +1,5 @@
 using System;
-using System.Collections.Concurrent;
 using System.ComponentModel;
-using System.Linq;
 using Android.App;
 using Android.Content;
 using Android.Content.Res;
@@ -9,7 +7,6 @@ using Android.OS;
 using Android.Views;
 using Android.Widget;
 using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
-using Xamarin.Forms.Internals;
 
 namespace Xamarin.Forms.Platform.Android
 {
@@ -53,8 +50,7 @@ namespace Xamarin.Forms.Platform.Android
                {
                        base.OnConfigurationChanged(newConfig);
                        EventHandler handler = ConfigurationChanged;
-                       if (handler != null)
-                               handler(this, new EventArgs());
+                       handler?.Invoke(this, new EventArgs());
                }
 
                // FIXME: THIS SHOULD NOT BE MANDATORY
@@ -84,28 +80,17 @@ namespace Xamarin.Forms.Platform.Android
 
                protected void LoadApplication(Application application)
                {
-                       if (application == null)
-                               throw new ArgumentNullException("application");
-
-                       (application as IApplicationController)?.SetAppIndexingProvider(new AndroidAppIndexProvider(this));
+                       if (_application != null)
+                               _application.PropertyChanged -= AppOnPropertyChanged;
 
-                       _application = application;
+                       _application = application ?? throw new ArgumentNullException(nameof(application));
+                       ((IApplicationController)application).SetAppIndexingProvider(new AndroidAppIndexProvider(this));
                        Xamarin.Forms.Application.SetCurrentApplication(application);
 
                        SetSoftInputMode();
 
                        application.PropertyChanged += AppOnPropertyChanged;
 
-                       if (application?.MainPage != null)
-                       {
-                               var iver = Platform.GetRenderer(application.MainPage);
-                               if (iver != null)
-                               {
-                                       iver.Dispose();
-                                       application.MainPage.ClearValue(Platform.RendererProperty);
-                               }
-                       }
-
                        SetMainPage();
                }
 
@@ -131,7 +116,7 @@ namespace Xamarin.Forms.Platform.Android
 
                        if (Forms.IsLollipopOrNewer)
                        {
-                               // Listen for the device going into power save mode so we can handle animations being disabled  
+                               // Listen for the device going into power save mode so we can handle animations being disabled
                                _powerSaveModeBroadcastReceiver = new PowerSaveModeBroadcastReceiver();
                        }
 
@@ -143,10 +128,12 @@ namespace Xamarin.Forms.Platform.Android
                        // may never be called
                        base.OnDestroy();
 
+                       if (_application != null)
+                               _application.PropertyChanged -= AppOnPropertyChanged;
+
                        PopupManager.Unsubscribe(this);
 
-                       if (Platform != null)
-                               ((IDisposable)Platform).Dispose();
+                       ((IDisposable) Platform)?.Dispose();
                }
 
                protected override void OnPause()
index 33c7620..f9d9dfc 100644 (file)
@@ -458,6 +458,11 @@ namespace Xamarin.Forms.Platform.Android
 
                internal void SetPage(Page newRoot)
                {
+                       if (Page == newRoot)
+                       {
+                               return;
+                       }
+
                        var layout = false;
                        List<IVisualElementRenderer> toDispose = null;