You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MAUI中Shell.Current.GoToAsync导航耗时过长问题求助

MAUI Shell导航性能异常排查求助

我在MAUI项目开发中遇到Shell导航性能问题,await Shell.Current.GoToAsync(nameof(DetailMenuPage));这条语句执行耗时高达4692ms,但导航前后的业务代码(包括页面Appearing触发的Load命令)总耗时仅168ms左右。

导航触发代码

public async Task SelectItem(object selectedCategorie)
{
   if (selectedCategorie is CategorieMenu)
   {
      var cSelectedCategorie = selectedCategorie as CategorieMenu;
      var sousCategorie = await _serviceToSousCategorieMenu.GetByCategorieMenuId(new List<int> { cSelectedCategorie.CategorieMenuId });
      StaticContext.CategorieMenuName = cSelectedCategorie.Name;
      StaticContext.SousCategorieMenu = sousCategorie;
      var watch = new System.Diagnostics.Stopwatch();
      watch.Start();
      await Shell.Current.GoToAsync(nameof(DetailMenuPage));
      watch.Stop();
      Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
   }
}

此处watch.ElapsedMilliseconds输出为4692ms。

页面加载业务代码

[RelayCommand]
public async Task Load()
{
   var watch = new System.Diagnostics.Stopwatch();
   watch.Start();
   var allItem = await _serviceMenuItem.GetBySousCategorieMenuId(StaticContext.SousCategorieMenu.Select(sc => sc.SousCategorieMenuId).ToList());
   if (allItem != null && allItem.Count > 0)
   {
      var groupedItem = allItem.GroupBy(u => u.SousCategorieMenuId).Select(grp => grp.ToList()).ToList();
      Title = StaticContext.CategorieMenuName;
      groupedItem.ForEach(c =>
      {
          Items.Add(new CategorieGroup
          (
             StaticContext.SousCategorieMenu.FirstOrDefault(sc => sc.SousCategorieMenuId == c.FirstOrDefault().SousCategorieMenuId).Name,
                    c
          ));
      });
   }
   watch.Stop();
   Console.WriteLine($"Execution Time: {watch.ElapsedMilliseconds} ms");
}

此处watch.ElapsedMilliseconds输出为168ms。

补充代码细节

DetailMenuPage构造函数

public DetailMenuPage(DetailMenuPageViewModel vm)
{
    InitializeComponent();
    BindingContext = vm;
}

DetailMenuPage的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"
             x:Class="Byron.Page.DetailMenuPage"
             xmlns:ViewModels="clr-namespace:Byron.ViewModel"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:DataType="ViewModels:DetailMenuPageViewModel"
             xmlns:Models ="clr-namespace:Byron.Model.DTO"
             xmlns:Converter="clr-namespace:Byron.Helper.Converter"
             xmlns:IHM ="clr-namespace:Byron.Model.IHM"
             Routing.Route="DetailPage"
             Title="{Binding Title}">
    <ContentPage.Behaviors>
        <toolkit:EventToCommandBehavior EventName="Appearing" Command="{Binding LoadCommand}" />
    </ContentPage.Behaviors>
    <ContentPage.Resources>
        <Converter:DoubleToStringConverter x:Key="doubleToStringConverter" />
    </ContentPage.Resources>
    
    
    <ScrollView>
        <StackLayout>
            <CollectionView ItemsSource="{Binding Items}" IsGrouped="True" >
                <CollectionView.GroupHeaderTemplate>
                    <DataTemplate x:DataType="IHM:CategorieGroup">
                        <StackLayout HorizontalOptions="FillAndExpand">
                            <Label Text="{Binding GroupTitle}" Style="{StaticResource TitleGroupMenu}"/>
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.GroupHeaderTemplate>
                <CollectionView.ItemTemplate>
                    <DataTemplate x:DataType="Models:MenuItem">
                        <Frame CornerRadius="10" Margin="10" BorderColor="{AppThemeBinding Light=Black, Dark=White}" BackgroundColor="Transparent">
                            <StackLayout Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="CenterAndExpand">
                                <StackLayout Orientation="Horizontal">
                                    <Label Text="{Binding Name}" Style="{StaticResource ItemMenu}" />
                                    <Label Text="{Binding Prix, Converter={StaticResource doubleToStringConverter}}" HorizontalOptions="EndAndExpand" Style="{StaticResource ItemMenu}"/>
                                </StackLayout>
                                <Rectangle HeightRequest="1" BackgroundColor="Black" Margin="0,0,100,0" />
                                <Label Text="{Binding Description}" VerticalOptions="Center" TextColor="{AppThemeBinding Light=Black, Dark=White}" />
                            </StackLayout>
                        </Frame>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </StackLayout>
    </ScrollView>
</ContentPage>

ViewModel构造函数

public DetailMenuPageViewModel(Services.SQLite.Interfaces.IServiceMenuItem serviceMenuItem)
 {
     _serviceMenuItem = serviceMenuItem;
 }

排查建议与解决方案

1. 检查路由与依赖注入配置

  • 确认DetailMenuPage的Shell路由注册无重复、无冲突,避免路由解析延迟。
  • 确保DetailMenuPage和对应的ViewModel在依赖注入中注册为瞬态(Transient),单例模式可能引发初始化时的资源竞争。

2. 优化XAML加载性能

  • 简化布局嵌套:CollectionView本身支持滚动,可直接移除外层的ScrollView和StackLayout,减少布局计算开销。
  • 启用XAML预编译:在项目文件中添加以下配置,提前编译XAML降低运行时加载耗时:
    <PropertyGroup>
        <MauiXamlCompile>True</MauiXamlCompile>
        <MauiXamlCompilationMode>Compile</MauiXamlCompilationMode>
    </PropertyGroup>
    
  • 替换高开销控件:用Border替代Frame(Frame渲染成本更高),并用Grid合并StackLayout嵌套,减少UI元素数量。

3. 排查主线程阻塞

  • 使用Visual Studio性能分析工具,监控导航过程中主线程的耗时操作,定位是否存在隐藏的同步阻塞代码。
  • 重构StaticContext数据传递逻辑,避免全局静态变量的线程竞争导致延迟。

4. 调整数据传递与导航逻辑

  • 改用Shell导航参数传递数据,替代StaticContext,将数据加载与导航解耦:
    // 导航时传递参数
    await Shell.Current.GoToAsync($"{nameof(DetailMenuPage)}?CategorieId={cSelectedCategorie.CategorieMenuId}");
    
    在ViewModel中通过QueryProperty接收参数并加载数据,避免导航等待数据准备完成。

5. 预加载页面优化首次导航

  • 如果仅首次导航耗时过长,可在App启动时预加载页面,提前完成JIT编译:
    // 在App构造函数或启动逻辑中添加
    _ = ServiceProvider.GetRequiredService<DetailMenuPage>();
    

内容的提问来源于stack exchange,提问作者Alexandre S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:42:21