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

.NET MAUI Problem with rendering ListView/CollectionView on Android #12070

Open
vsfeedback opened this issue Dec 13, 2022 · 13 comments
Open

.NET MAUI Problem with rendering ListView/CollectionView on Android #12070

vsfeedback opened this issue Dec 13, 2022 · 13 comments
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView delighter-sc platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.)
Milestone

Comments

@vsfeedback
Copy link

vsfeedback commented Dec 13, 2022

This issue has been moved from a ticket on Developer Community.


[severity:It’s more difficult to complete my work]
I have a program on the MAUI platform with the MVVM pattern. I’m doing it now for Android and there is a problem with rendering ListView/CollectionView:
The problem is the long rendering of ListView or CollectionView on Android phones. Here you have an empty application screen with an empty ListView. You click the “Add 20 items” button. And the User interface “freezes for 2 seconds” on the android 10 version is about 3 seconds, on android 13 it is already 1.5 seconds. Provided that you have only 8 Labels, but as soon as you add another picture or more Labels, etc., the loading time will increase even more.

Example:

C#

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace MauiApp1;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        BindingContext = new MainPageModel();
    }
}

public class MainPageModel : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler? PropertyChanged;

    public ICommand ButtonCommand => new Command(UpdateList);

    private void UpdateList()
    {
        List list = new();
        for (int i = 0; i < 20; i++)
        {
            list.Add(new MainPageModel()
            {
                Example = "Text",
                Test = "Test"

            });
        }
        MyItems = new ObservableCollection(list);

    }

    public ObservableCollection MyItems
    {
        get => _MyItems;
        set
        {
            _MyItems = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyItems)));
        }
    }
    private ObservableCollection _MyItems = new ObservableCollection();

    public string Example
    {
        get => _example;
        set
        {
            _example = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Example)));
        }
    }
    private string _example;

    public string Test
    {
        get => _test;
        set
        {
            _test = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Test)));
        }
    }
    private string _test;
}

  

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="MauiApp1.MainPage"
             xmlns:local="clr-namespace:MauiApp1"
             x:DataType="local:MainPageModel">
    <ScrollView Padding="6">
        <VerticalStackLayout>
            <Button Text="Add 20 items" Command="{Binding ButtonCommand}" />
            <ListView ItemsSource="{Binding MyItems}" HasUnevenRows="True">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="local:MainPageModel">
                        <ViewCell>
                            <Grid>
                                <VerticalStackLayout>
                                    <VerticalStackLayout Margin="0,12,0,0">
                                        <Label Text="{Binding Example}"  />
                                        <Label Text="{Binding Example}"  />
                                        <Label Text="{Binding Example}"  />
                                        <Label Text="{Binding Example}"  />
                                    </VerticalStackLayout>
                                    <VerticalStackLayout Margin="0,12,0,0">
                                        <Label Text="{Binding Test}"  />
                                        <Label Text="{Binding Test}"  />
                                        <Label Text="{Binding Test}"  />
                                        <Label Text="{Binding Test}"  />
                                    </VerticalStackLayout>
                                </VerticalStackLayout>
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </VerticalStackLayout>
    </ScrollView>
</ContentPage>

PS: Don’t track the rendering using Stopwatch. Since the “user interface” itself freezes, it is easily visible if you add a Gif image next to the button and notice the “GIF freezing” when you click on the button.


Original Comments

Feedback Bot on 12/4/2022, 04:35 PM:

(private comment, text removed)


Original Solutions

(no solutions)

@LennoxP90
Copy link

+1

@Odaronil
Copy link

you copied my XAML code incorrectly from the Developer Community. Please correct it.

@jsuarezruiz jsuarezruiz added platform/android 🤖 area-controls-collectionview CollectionView, CarouselView, IndicatorView labels Dec 14, 2022
@needledrag
Copy link

Any update on this? I have a similar problem, when adding items to the CollectionView and you exceed the height of the CV in terms of items all further updates to the CV slow down, including when you initially load it with a number of items that exceed the visible area of the CV. This doesn't occur when a fixed height is set on the CV though.

@Odaronil
Copy link

Any update on this? I have a similar problem, when adding items to the CollectionView and you exceed the height of the CV in terms of items all further updates to the CV slow down, including when you initially load it with a number of items that exceed the visible area of the CV. This doesn't occur when a fixed height is set on the CV though.

No, Microsoft is silent...

@Ghostbird
Copy link
Contributor

Ghostbird commented Feb 20, 2023

To me it seems that “Microsoft is slient” on this, because you're simply making one of the basic mistakes that most developers make at least once, when they start building a GUI. You're doing heavy lifting on the UI thread, and wonder why the UI doesn't respond to input, while it's running your calculations. This isn't MAUI specific, nor Microsoft specific, though here's a quick piece on it by Microsoft. This applies to almost any application that has both a graphical user interface and an event-driven way of interacting with it. The same applies when you're doing web-development, though in that case sometimes you'll use a framework that mitigates the effects. The basic lesson is: Do not do calculations on the UI thread except those have to be done on the UI In the latter category you'll find those actions directly (not bindings) impacting the UI in meaningful ways .

What happens if you use this instead?

    private void UpdateList()
    {
        _ = Task.Run(() => {
          List list = new();
          for (int i = 0; i < 20; i++)
          {
              list.Add(new MainPageModel()
              {
                  Example = "Text",
                  Test = "Test"
              });
          }
          MyItems = new ObservableCollection(list);
      });
    }

@Odaronil
Copy link

Odaronil commented Feb 20, 2023

To me it seems that “Microsoft is slient” on this, because you're simply making one of the basic mistakes that most developers make at least once, when they start building a GUI. You're doing heavy lifting on the UI thread, and wonder why the UI doesn't respond to input, while it's running your calculations. This isn't MAUI specific, nor Microsoft specific, though here's a quick piece on it by Microsoft. This applies to almost any application that has both a graphical user interface and an event-driven way of interacting with it. The same applies when you're doing web-development, though in that case sometimes you'll use a framework that mitigates the effects. The basic lesson is: Do not do calculations on the UI thread except those have to be done on the UI In the latter category you'll find those actions directly (not bindings) impacting the UI in meaningful ways .

What happens if you use this instead?

    private void UpdateList()
    {
        _ = Task.Run(() => {
          List list = new();
          for (int i = 0; i < 20; i++)
          {
              list.Add(new MainPageModel()
              {
                  Example = "Text",
                  Test = "Test"
              });
          }
          MyItems = new ObservableCollection(list);
      });
    }

In my opinion, you misunderstand, this is a demo code that shows an "error" specifically in rendering on Android. What you write is obvious and easy to implement, but this does not solve the problem that the List "eating" a lot of resources due to the calculation of each cell. No matter what you do and in what stream, your resources will be spent on "Drawing" and calculating the size of cells - this is a mistake! (Because there is no such problem on Xamarin Android and so on. This is a disease of MAUI, as with resources on Windows, as with the fact that it does not work at all on iOS). Before writing a comment, I really ask you to first check what you are suggesting and get to the bottom of the problem.

PS: You can only "solve the problem" by setting a fixed list height, but the interface will twitch when rendering. The list will be loaded instantly, but this is how it should be without setting a fixed height!

@Ghostbird
Copy link
Contributor

Apologies, I though this was purely a UI thread blocking issue. I'm curious what you mean by the fact that it does not work at all on iOS. I have only encountered one error on iOS with dynamic ListViews so far, which has to do with the ItemTapped handling¹. I did note that the MAUI performance isn't amazing, but what I've encountered so far has mainly been due to the complexity of my lists. I draw a list where each cell is a complex individually drawn grid, and when I start adding more than fit on the screen, and rapidly swipe down, there's clearly some rendering lag and FPS dips
down on Android, but nothing like what you see. My code is a lot more complicated than this example, and maybe there's something in there that fixes it. One thing I have done, is bind HeightRequestProperty with a converter that calculates the desired height from the number of items in the list it gets as input. Ultimately it didn't solve my issue, but maybe it will work in your case? Another difference is that my ListView doesn't involve any xaml, it would be weird if that mattered though.

If you can pinpoint the issue, I'd encourage you to make a PR. I recently ran into a bug on Android, made a minimalistic fix for it, and made a PR. It was merged pretty quickly, and the maintainers immediately also backported it to .NET 7. It will be in the next service release.

  1. Searching to see whether others encountered something similar landed me on this issue.

@Odaronil
Copy link

Apologies, I though this was purely a UI thread blocking issue. I'm curious what you mean by the fact that it does not work at all on iOS. I have only encountered one error on iOS with dynamic ListViews so far, which has to do with the ItemTapped handling¹. I did note that the MAUI performance isn't amazing, but what I've encountered so far has mainly been due to the complexity of my lists. I draw a list where each cell is a complex individually drawn grid, and when I start adding more than fit on the screen, and rapidly swipe down, there's clearly some rendering lag and FPS dips down on Android, but nothing like what you see. My code is a lot more complicated than this example, and maybe there's something in there that fixes it. One thing I have done, is bind HeightRequestProperty with a converter that calculates the desired height from the number of items in the list it gets as input. Ultimately it didn't solve my issue, but maybe it will work in your case? Another difference is that my ListView doesn't involve any xaml, it would be weird if that mattered though.

If you can pinpoint the issue, I'd encourage you to make a PR. I recently ran into a bug on Android, made a minimalistic fix for it, and made a PR. It was merged pretty quickly, and the maintainers immediately also backported it to .NET 7. It will be in the next service release.

  1. Searching to see whether others encountered something similar landed me on this issue.

Unfortunately, if I knew the solution or understood exactly where the problem was, I would have written here right away.

IOS Problem with ListView/CollectionView - #12071
Windows Problem with ListView/CollectionView - #9162

MAUI has problems with list on different platforms...

I take it you don't use XAML at all?

@Ghostbird
Copy link
Contributor

I do use XAML, but it's a mix. For more dynamic components, I don't. For fairly static stuff I do use it. Though if I were to build a new MAUI app, I'd seriously consider not using XAML at all. The one I'm currently working with was ported from Xamarin Forms, and it made no sense to rewrite it completely.

@PureWeen
Copy link
Member

PureWeen commented Mar 2, 2023

Related #12130

@PureWeen PureWeen added the legacy-area-perf Startup / Runtime performance label Mar 2, 2023
@PureWeen PureWeen added this to the Backlog milestone Mar 2, 2023
@ghost
Copy link

ghost commented Mar 2, 2023

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@samhouts samhouts added the t/bug Something isn't working label Jul 31, 2023
@sk1llsh0t
Copy link

sk1llsh0t commented Nov 17, 2023

I'm experiencing the same thing on Android as well. I have a collectionview that ran very smoothly in xamarin forms but after the conversion to maui, it is rendered extremely slowly. I even use a "please wait" spinner when navigating to the page. Then when the page appearing event is fired, i hide the spinner. After the spinner disappears, it takes the collectionview another 10 seconds to actually show on the blank screen. I expect the page appearing event to fire only after all child elements have been drawn. The app just appears to be frozen and unresponsive. Even after rendering, scrolling can be choppy and laggy as well.

I did convert the collectionview to a bindablelayout wrapped in a scrollview. This actually solves the laggy, choppiness while scrolling but still takes forever to draw on the screen. I don't consider a bindablelayout wrapped in a scrollview a solution as it isn't UI optimized like the collectionview is (should be).

I just updated it to .NET 8.0 but that didn't seem to have any affect either.

@Zhanglirong-Winnie Zhanglirong-Winnie added s/verified Verified / Reproducible Issue ready for Engineering Triage s/triaged Issue has been reviewed labels Nov 28, 2023
@Zhanglirong-Winnie
Copy link

Verified this issue with Visual Studio Enterprise 17.9.0 Preview 1.0. Can repro on android platform.

@Eilon Eilon added t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.) and removed legacy-area-perf Startup / Runtime performance labels May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-controls-collectionview CollectionView, CarouselView, IndicatorView delighter-sc platform/android 🤖 s/triaged Issue has been reviewed s/verified Verified / Reproducible Issue ready for Engineering Triage t/bug Something isn't working t/perf The issue affects performance (runtime speed, memory usage, startup time, etc.)
Projects
None yet
Development

No branches or pull requests