Application.Current.MainPage vs Navigation.PushAsync()vs Navigation.PushModalAsync()

时间:2017-10-24 13:39:35

标签: c# xamarin xamarin.forms navigationbar

我正在开发一个不需要后退按钮的Xamarin Forms App(PCL)。该应用有三个页面:SplashScreenPage用于加载数据,LoginPage用户需要登录,RootPageMasterDetailPage。我想知道在页面之间导航的最佳选择是什么(例如,为了避免内存泄漏):

第一个解决方案:

Application.Current.MainPage = new ContentPage();

第二个解决方案:

Navigation.PushAsync(new NavigationPage(new ContentPage()));

然后

NavigationPage.SetHasNavigationBar(this, false);
ClearNavigationStack();

第三种解决方案

await Navigation.PushModalAsync(new NavigationPage(new ContentPage()));

然后

NavigationPage.SetHasNavigationBar(this, false);
ClearModalStack();

2 个答案:

答案 0 :(得分:4)

正如@ will-decter所描述的,如果正确实施,上述解决方案都不会导致内存泄漏。

您可以使用上述任何解决方案。通常你不需要做任何事情来清除前一页。垃圾收集器会自动为您执行此操作(不是立即执行,但根据某些条件在一段时间后)。考虑第一个解决方案:

Application.Current.MainPage = new Page1();

现在,如果你指定这样的新页面。

Application.Current.MainPage = new Page2();

由于Page1不再使用,GC会在GC尝试回收一些内存后一段时间收集Page1对象。您也可以使用GC.Collect()强制GC立即回收内存,但由于GC.Collect()操作很昂贵,所以我建议您不要在代码中调用它而是优化代码,所以不需要叫它。

但是如果您的页面订阅了一个事件并且没有取消订阅,那么即使您调用GC.Collect()方法,GC也无法收集该页面。因此,请确保您取消订阅任何订阅的活动,如下所示:

public class MainPage : ContentPage
{
     protected override void OnAppearing()
     {
         base.OnAppearing();
         MyEntry.TextChanged += MyEntry_TextChanged;
     }

     protected override void OnDisappearing()
     {
         base.OnDisappearing();
         MyEntry.TextChanged -= MyEntry_TextChanged;
     }
}

(如果事件是从xaml订阅的话,你可以跳过unsubscibe,因为Xamarin Form使用了WeakReference)

这将确保GC在需要时收集MainPage。

我建议您阅读this文章,以便更好地了解GC如何在Xamarin中运行,以及如何提高应用程序性能。

https://developer.xamarin.com/guides/cross-platform/deployment,_testing,_and_metrics/memory_perf_best_practices/

答案 1 :(得分:3)

认为在页面之间导航的最佳选择是

在App.cs中

void OnLoginClicked(object sender, EventArgs e)
{
    Application.Current.MainPage = new NavigationPage(new MasterPage());
}

然后登录成功点击:

console.log

不需要添加“NavigationPage.SetHasNavigationBar(this,false);”