【问题标题】:When are .NET MAUI (Xamarin Forms) pages/custom views destroyed?.NET MAUI (Xamarin Forms) 页面/自定义视图何时被销毁?
【发布时间】:2022-11-08 03:38:35
【问题描述】:

我是 Xamarin/.NET MAUI 应用程序开发的新手。我开始为 Android 设备开发一个示例 .NET MAUI 应用程序。
我试图了解页面和我的自定义视图如何/何时被销毁(处置)。我阅读了一些网页,但我无法真正理解 .NET MAUI(或 Xamarin)中的工作原理。

我有三个页面:MainPage、SecondPage、TestMapPage。
SecondPage 有一个导航到TestMapPage 的按钮。它实例化一个TestMapPage 对象并将其传递给Navigation.PushAsync()。
TestMapPage 包含一个自定义视图TestMapView,它由我的自定义视图渲染器TestMapViewRenderer 渲染。我在渲染器中创建了一个MapView 对象(来自Naxam.Mapbox.Droid)并在TestMapPage 中显示地图。该地图出现在模拟器上,并且工作正常。

我认为当我导航回MainPage 时,SecondPage、TestMapPage 和TestMapView(以及TestMapViewRenderer 中的所有对象)将被销毁。但是,当我在渲染器中的 Dispose() 上设置断点并导航回 SecondPage 或 MainPage in 时,它永远不会被击中。

我的问题:

  1. 当我返回MainPage 时,SecondPage、TestMapPage、TestMapView 以及视图和视图渲染器中的所有其他对象(如MapboxMap)是否保留在某个地方?
  2. 页面和视图何时被销毁/处置?
  3. 如果这些页面对象在应用程序关闭之前一直保存在某个地方,这是正常行为吗?
  4. 如果不是正常行为,我该如何解决?

    我担心内存泄漏...

    MainPage.xaml.cs

    public partial class MainPage : ContentPage
    {
        // ...
        private async void OnGoToSecondPageClicked(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new SecondPage());
        }
    }
    

    SecondPage.xaml.cs

    public partial class SecondPage : ContentPage
    {
        // ...
        private async void OnMapShowClicked(object sender, EventArgs e)
        {
            await Navigation.PushAsync(new TestMapPage());
        }
    }
    

    TestMapPage.xaml

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:MapTest"
                 x:Class="MapTest.TestMapPage">
        <StackLayout Margin="5">
            <local:TestMapView
                x:Name="map"
                VerticalOptions="FillAndExpand" 
                HorizontalOptions="CenterAndExpand"/>
        </StackLayout>
    </ContentPage>
    

    TestMapView.cs

    public class TestMapView : View { }
    

    TestMapViewRenderer.cs

    public partial class TestMapViewRenderer : ViewRenderer<TestMapView, Android.Views.View>
    {
        private MapboxMap map;
    
        public TestMapViewRenderer(Context context) : base(context) {}
    
        protected override void OnElementChanged(ElementChangedEventArgs<TestMapView> e)
        {
            base.OnElementChanged(e);
            // ...
            if (Control == null)
            {
                var mapView = new MapView(Context);
                SetNativeControl(mapView);
                mapView.GetMapAsync(this);
            }
        }
    
        public void OnMapReady(MapboxMap map)
        {
            this.map = map;
            this.map.SetStyle(Resources.GetString(Resource.String.mapbox_style_satellite), this);
        }
    
        protected override void Dispose(bool disposing)
        {
            // A breakpoint never hits on this line. Why?
            base.Dispose(disposing);
        }
        // ...
    }
    

【问题讨论】:

  • 仅供参考,请参阅相关问题Dispose Xamarin Forms Views/Pages?。此外,请务必在您的测试中致电GC.Collect/GC.WaitForPendingFinalizers。 (您可能不想在生产中这样做——在任何 GC 系统中过于频繁地强制 GC 可能会适得其反。)

标签: xamarin.android maui


【解决方案1】:

我所知道的;

  1. 不,在每次导航时,您都会创建新的页面实例,因此,页面由 .NET 自己创建并保存在内存中,一旦垃圾收集达到某个阈值,内存将被释放。在那之前,这些页面都在内存中,但不打算在将来的某个时候使用。
  2. 当 GC 决定时,Xamarin/MAUI 不关心视图。
  3. 很遗憾,是的。
  4. 这很正常,您可以通过使用@ToolmakerSteve 所指的内容来克服。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    • 2022-08-21
    • 2018-09-08
    • 2018-03-19
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    相关资源
    最近更新 更多