FreshMvvm icon indicating copy to clipboard operation
FreshMvvm copied to clipboard

RemoveFromNavigation Keeps Page and PageModel Alive

Open Chrisb1481 opened this issue 7 years ago • 3 comments

If you remove a page from the navigation stack by calling:

CoreMethods.RemoveFromNavigation<PageModelHere>();

The PageModel is kept alive because the next PageModel in the stack still holds a reference to it in PreviousPageModel. The Page is also kept alive because the PageModel has a reference to it.

This isn't a problem if you are removing the previous Page from the navigation, as in: Page A > Page B inside Page B's PageModel you would do:

CoreMethods.RemoveFromNavigation<ExtendedSplashPageModel>(true);
PreviousPageModel = null;

Now Page A and Page A's PageModel are cleared from memory.

In my case I was just removing the previous page from the navigation stack, so it was simple to fix my little leak. If you have a complex navigation stack, I imagine it can get a little tricky to find the right PageModel to remove the PreviousPageModel from.

Chrisb1481 avatar Aug 17 '18 13:08 Chrisb1481

Are you sure with that? did you profile it? i have this usage also very often and i am seeing that pages are removed without from the stack(not sure about memory). because when I click back button i am not page A. i never needed PreviousPageModel = null; How did you come to that conclusion?

EmilAlipiev avatar Oct 11 '18 23:10 EmilAlipiev

if your theory is correct, it will be enough to extend


  /// <summary>
        /// Remove specific page/pagemodel from navigation
        /// </summary>
        public void RemoveFromNavigation<TPageModel> (bool removeAll = false) where TPageModel : FreshBasePageModel
        {
            //var pages = this._currentPage.Navigation.Where (o => o is TPageModel);
            foreach (var page in this._currentPage.Navigation.NavigationStack.Reverse().ToList()) 
            {
                if (page.BindingContext is TPageModel) 
                {
                    page.GetModel()?.RaisePageWasPopped ();
                    this._currentPage.Navigation.RemovePage (page);
                    if (_currentPageModel.PreviousPageModel is TPageModel)
                        _currentPageModel.PreviousPageModel = null;

                        if (!removeAll)
                        break;
                }
            }
        }

But how should we handle in case we have navigation like below

A->B->C->D

you want to remove B and C when you are on D. I guess if you remove C successfully without having any reference on D. B should be also removed.


CoreMethods.RemoveFromNavigation<CPageModel>(true);
CoreMethods.RemoveFromNavigation<BPageModel>(true);

EmilAlipiev avatar Oct 11 '18 23:10 EmilAlipiev

Depends how you want to do it. If you have A->B->C->D and you remove B and C, you could update Ds PreviousPageModel to A or just null it. In my app it starts and I show an ExtendedSplashPage on Android and UWP. The ExtendedSplashPage just does some loading and initializing then pushes the Home Page. I only do it this way because when setting MainPage in Xamarin Forms it causes a brief flicker. So I just set the MainPage to my NavigationContainer and then remove the ExtendedSplashPage because its only needed briefly in the beginning and then never again.

Chrisb1481 avatar Oct 11 '18 23:10 Chrisb1481