Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Performance issue] Creation and display of ContentView takes too long when displayed for the first time #25754

Open
MAUIoxo opened this issue Nov 8, 2024 · 1 comment
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter t/bug Something isn't working t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf)
Milestone

Comments

@MAUIoxo
Copy link

MAUIoxo commented Nov 8, 2024

Description

I have a ContentView in XAML that is displayed after switching a tab.
The ContentView is not too complicated in my opinion:

<Grid VerticalOptions="StartAndExpand">

    <!-- Can't use the BackgroundImageView here since there is a Bug that draws the image too big there is a gray stipe at the bottom -->
    <Image x:Name="BackgroundImage" Source="background_image.jpg" VerticalOptions="StartAndExpand" HorizontalOptions="FillAndExpand" Aspect="AspectFill" Margin="{OnPlatform Android='0, -40, 0, 0', Default='0'}"/>

    <Border x:Name="OverviewBorder" Grid.Row="0" Style="{StaticResource BorderStyleView}" VerticalOptions="StartAndExpand">

        <Grid RowDefinitions="Auto, *">

            <!--Search...-->
            <SearchBar Grid.Row="0" ios:SearchBar.SearchBarStyle="Minimal" Text="{Binding SearchText}" Placeholder="Search Text ..." />

            <!-- CollectionView: Margin to get the ScrollBar to the right and closer to the Border -->
            <dx:DXCollectionView Grid.Row="1" ItemsSource="{Binding AvailableItems, Mode=TwoWay}" AllowGroupCollapse="False" FilterExpression="{Binding SearchFilterExpression}" Margin="10, 5, 10, 15">

                <!-- Group Description: FieldName used to group the items and Order in which they are grouped -->
                <dx:DXCollectionView.GroupDescription>
                    <dx:GroupDescription FieldName="Name" GroupInterval="Alphabetical"/>
                </dx:DXCollectionView.GroupDescription>
                
                <!-- Group Header: to group items -->
                <dx:DXCollectionView.GroupHeaderTemplate>
                    <DataTemplate>
                        <VerticalStackLayout>
                            <Label Text="{Binding Value, StringFormat=' {0}'}" Style="{StaticResource GroupHeaderStyle}" />
                            <BoxView Style="{StaticResource GroupHeaderUnderlineStyle}"/>
                        </VerticalStackLayout>
                    </DataTemplate>
                </dx:DXCollectionView.GroupHeaderTemplate>

                <!-- Group Items -->
                <dx:DXCollectionView.ItemTemplate>
                    <DataTemplate x:DataType="{x:Type databaseModels:Food}">

                        <controls:CustomSwipeView SwipeViewOpenFlag="{Binding SwipeViewOpenFlag, Source={RelativeSource AncestorType={x:Type viewModels:OverviewViewModel}}, Mode=TwoWay}">

                            <Border Padding="20, 15, 20, 10" Style="{StaticResource BorderRoundedCornerStyle}">
                                <VerticalStackLayout x:DataType="databaseModels:Food">

                                    <!-- Name -->
                                    <Label Text="{Binding Name}" FontSize="13" FontAttributes="Bold" />


                                    <!-- Brand -->
                                    <Label Text="{Binding Brand}" FontSize="12" FontAttributes="Bold" TextColor="{StaticResource Gray500}" Margin="0, 5, 0, 0"/>


                                    <!-- Bottom Row for values -->
                                    <HorizontalStackLayout Margin="0, 15, 0, 0">
                                        <HorizontalStackLayout HorizontalOptions="StartAndExpand">
                                            <Image Source="dotnet_bot.png" HeightRequest="12" WidthRequest="12" Margin="0, 1, 5, 5"/>
                                            <Label Text="Value 1:" Style="{StaticResource SelectionDetailsLabelStyle}" />
                                            <labelControls:CultureBasedNumberLabel Text="{Binding Fats, Mode=OneWay, StringFormat='  {0:0.###}'}" Style="{StaticResource SelectionDetailsValueStyle}" />
                                        </HorizontalStackLayout>

                                        <HorizontalStackLayout HorizontalOptions="CenterAndExpand" Margin="5, 0, 0, 0">
                                            <Image Source="dotnet_bot.png" HeightRequest="20" WidthRequest="20" Margin="0, -2, 0, 0" />
                                            <Label Text="Value 2:" Style="{StaticResource SelectionDetailsLabelStyle}"/>
                                            <labelControls:CultureBasedNumberLabel Text="{Binding Carbohydrates, Mode=OneWay, StringFormat='  {0:0.###}'}" Style="{StaticResource SelectionDetailsValueStyle}" />
                                        </HorizontalStackLayout>

                                        <HorizontalStackLayout HorizontalOptions="EndAndExpand" Margin="5, 0, 0, 0">
                                            <Image Source="dotnet_bot.png" HeightRequest="16" WidthRequest="16" Margin="5, -1, 3, 2" />
                                            <Label Text="Value 3:" Style="{StaticResource SelectionDetailsLabelStyle}"/>
                                            <labelControls:CultureBasedNumberLabel Text="{Binding Proteins, Mode=OneWay, StringFormat='  {0:0.###}'}" Style="{StaticResource SelectionDetailsValueStyle}" />
                                        </HorizontalStackLayout>
                                    </HorizontalStackLayout>

                                </VerticalStackLayout>
                            </Border>

                            <SwipeView.RightItems>
                                <SwipeItems>
                                    <SwipeItemView>

                                        <Grid RowDefinitions="*" ColumnDefinitions="*, *" WidthRequest="160" HeightRequest="100" ColumnSpacing="0">
                                            <Label Grid.Column="0" Text="Edit" BackgroundColor="LightGrey" Style="{StaticResource SwipeItemStyle}">
                                                <Label.GestureRecognizers>
                                                    <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:OverviewViewModel}}, Path=EditFoodItemCommand}" CommandParameter="{Binding .}"/>
                                                </Label.GestureRecognizers>
                                            </Label>

                                            <Label Grid.Column="1" Text="Delete" BackgroundColor="{StaticResource DarkOrange1}" TextColor="White" Style="{StaticResource SwipeItemStyle}">
                                                <Label.GestureRecognizers>
                                                    <TapGestureRecognizer Command="{Binding Source={RelativeSource AncestorType={x:Type viewModels:OverviewViewModel}}, Path=DeleteFoodItemCommand}" CommandParameter="{Binding .}"/>
                                                </Label.GestureRecognizers>
                                            </Label>
                                        </Grid>

                                    </SwipeItemView>
                                </SwipeItems>
                            </SwipeView.RightItems>

                        </controls:CustomSwipeView>

                    </DataTemplate>
                </dx:DXCollectionView.ItemTemplate>

            </dx:DXCollectionView>
            
        </Grid>
        
    </Border>

</Grid>


Nevertheless, the creation of this ContentView when displayed for the first time takes too long so that there is a bad user experience which is like having a lagging UI:


The example uses Sharpnado.Tabs to switch between the Views. This component allows 3 different kinds of Views, a LazyView, DelayedView (which shows an activity indicator while loading the View) and also a normal .NET MAUI View. I tried all of them and they show the same behavior. LazyView and normal .NET MAUI View feel like they are laggy since the View does not show up instantly after clicking the Tab and they show up with a delay with is too long and not acceptable in my opinion. Even on my local iPhone 14 Pro Max it is laggy after clicking.

The DelayedView switches to the View faster and at least shows the background and some things that show the user that her click was performed. But this View also displays an ActivityIndicator that runs until the View is fully loaded to bridge the wait time for the user and make this delay more acceptable. However, if only 2-3 elements are displayed afterwards in the CollectionView and not hundreds of elements, it still feels strange to the customer why they see a spinning hourglass for only so few items. The question remains, though, why the creation of the View has to take so long when displayed for the first time. For me, this is a fundamental issue in .NET MAUI.

After it was displayed for the first time it is possible to fluently switch back and forth between the tabs:




  • I tried to create this ContentView including its ViewModel in advance and assign its content when the Tab was clicked (Caching of the View), but this did not help
  • I also use [XamlCompilation(XamlCompilationOptions.Compile)], but this also did not help to prevent this delay when created for the first time
  • I can see and reproduce it in Debug as well as deployed Release to my local iPhone

Steps to Reproduce

  1. The attached minimal reproducible example uses a "DevExpress" DXCollectionView as the performance is usually better
  2. To reproduce the example, you can Obtain a Personal NuGet Feed URL here
  3. Start the App of the attached Project
  4. Click on "Tab 2" and see the user experience after you've clicked the tab
  5. Switch between "Tab 1" and "Tab 2" back and forth and see that the user experience is as it should be
  6. Bottom line is: the first creation and display of a ContentView like that takes too long and is a performance issue

Link to public reproduction project repository

DisplayViewDelay_25754

Version with bug

8.0.92 SR9.2

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

iPhone 15 Pro Max iOS 17.4

Did you find any workaround?

No workaround so far

  • I also tried to create this ContentView including its ViewModel in advance and assign its content when the Tab was clicked (Caching of the View), but this did not help.
  • I also used [XamlCompilation(XamlCompilationOptions.Compile)], but this also did not help

Relevant log output

@MAUIoxo MAUIoxo added the t/bug Something isn't working label Nov 8, 2024
@mattleibow mattleibow added the t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf) label Nov 12, 2024
@mattleibow mattleibow added this to the Backlog milestone Nov 12, 2024
@mattleibow
Copy link
Member

One thing that might help is if you ran a profiler on the app and attach a speedscope: https://github.com/dotnet/maui/wiki/Profiling-.NET-MAUI-Apps

Maybe something will appear like loading some data/image in the constructor or another part of the binding. Maybe there is a lay loading something from the DB in a binding.

@mattleibow mattleibow added the area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter label Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter t/bug Something isn't working t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) (sub: perf)
Projects
None yet
Development

No branches or pull requests

2 participants