DataGrid takes to much RAM

4 posts, 0 answers
  1. vasil
    vasil avatar
    1 posts
    Member since:
    Dec 2017

    Posted 02 Feb 2018 Link to this post

    Hi.I get this error when RadDataGrid.ItemSource have 100 or more objects.

    On Samsung Galaxy S6 edge = Java.Lang.OutOfMemoryError: Failed to allocate a 463014412 byte allocation with 10286048 free bytes and 241MB until OOM

    On Pixel 2 XL ->  error [ERROR] FATAL UNHANDLED EXCEPTION: Java.Lang.RuntimeException: Canvas: trying to draw too large(346442880bytes) bitmap.

     

    This is the code that triggers this error.

    Brand new project(.NET)

    using System.Collections.Generic;
    using Telerik.XamarinForms.DataGrid;
    using Xamarin.Forms;

    namespace test
    {
        public partial class MainPage : ContentPage
        {
            public MainPage()
            {
                InitializeComponent();

                RadDataGrid gridView = new RadDataGrid();

                var data = new List<object>();

                for (int i = 0; i < 100; i++)
                {
                    data.Add(new ViewModelData()
                    {
                        Data1 = "Data " + i,
                        Data2 = "Data " + i,
                        Data3 = "Data " + i,
                        Data4 = "Data " + i,
                        Data5 = "Data " + i,
                        Data6 = "Data " + i,
                        Data7 = "Data " + i,
                        Data8 = "Data " + i,
                        Data9 = "Data " + i,
                        Data10 = "Data " + i,
                        Data11 = "Data " + i,
                        Data12 = "Data " + i,
                        Data13 = "Data " + i,
                        Data14 = "Data " + i,
                        Data15 = "Data " + i,
                    });
                }

                gridView.ItemsSource = data;

                 //container is stacklayout and none of his properties are set.

                container.Children.Add(gridView);
            }
        }

        public class ViewModelData
        {
            public string Data1 { get; set; }
            public string Data2 { get; set; }
            public string Data3 { get; set; }
            public string Data4 { get; set; }
            public string Data5 { get; set; }
            public string Data6 { get; set; }
            public string Data7 { get; set; }
            public string Data8 { get; set; }
            public string Data9 { get; set; }
            public string Data10 { get; set; }
            public string Data11 { get; set; }
            public string Data12 { get; set; }
            public string Data13 { get; set; }
            public string Data14 { get; set; }
            public string Data15 { get; set; }
        }
    }

    //Xaml Code

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:test"
                 x:Class="test.MainPage">

            <StackLayout x:Name="container">
                
            </StackLayout>

    </ContentPage>

  2. Petar Marchev
    Admin
    Petar Marchev avatar
    1029 posts

    Posted 07 Feb 2018 Link to this post

    Hello Vasil,

    A StackLayout in Xamarin Forms works in such a way that it measures its children with Infinity. Because of this it is possible that a child is laid out with a much larger size than the StackLayout actually has. Let say that the stack layout has 500 pixels available vertically, and the DataGrid has 1000 items. If each item has to be 40 pixels in height, the desired size of the DataGrid will be about 40000. The StackLayout will respect that and the data grid will be laid out with that size. But now, the data grid will realize all visual items, it will try to create a huge bitmap in which to draw (because it uses SkiaSharp for rendering), and this will lead to a massive memory allocation. Even if the application did not run out of memory, now the DataGrid is close to useless because it managed to show all of its items, and no scrolling will be available.

    In your current setup I see that you only put the DataGrid inside of the StackLayout and if that is the same in your actual application, I suggest you do not use the StackLayout at all. If you do need to add more items, perhaps you can use a Grid, or if you insist on a StackLayout you could utilize the FillAndExpand VerticalOptions very carefully. Let us know if you need further assistance.

    Regards,
    Petar Marchev
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. Cesar
    Cesar avatar
    3 posts
    Member since:
    Mar 2018

    Posted 17 Jul 2018 in reply to Petar Marchev Link to this post

    Hi Petar,

    I'm having the same issue, but i actually don't use a StackLayout as the container for the grid. instead, I use a ScrollView. I get the same error about the canvas being too large with 100+ items. It happens only on Android though, iOS doesn't seem to have issues with large amounts of data. Are there any other suggestions on how to fix this?

    Thanks,

  4. Lance | Manager Technical Support
    Admin
    Lance | Manager Technical Support avatar
    1186 posts

    Posted 17 Jul 2018 Link to this post

    Hi Cesar,

    This is fundamentally the same problem. A ScrollView on Android will give an infinite canvas for it's children to render, even though they're not visible in the view port.

    Solutions

    Use a Suitable Parent

    Use a parent container that the DataGrid will get a valid measurement from. For example, a Grid:

    <ContentPage>
        <Grid>
            <dataGrid:RadDataGrid x:Name="radDataGrid" />
        </Grid>
    </ContentPage>

    if you need the Grid to have RowDefinitions, make sure the DataGrid is not in an Auto sized RowDefinition (this also measures to infinity). You can use star-sized or explicit sized RowDefinition safely.


    Set Height and Width Request

    Set the DataGrid's HieghtRequest and WidthRequest, so that the DataGrid doesn't try to draw all of its content.

    If you don't want to accidentally set the size too small, you could always use another element on the page to get the values. For example, you could use the ContentPage's rendered height and width:

    <ContentPage x:Name="page">
     
        <dataGrid:RadDataGrid x:Name="radDataGrid"
                  WidthRequest="{Binding Width, Source={x:Source page}}"
                  HeightRequest="{Binding Height, Source={x:Source page}}" />
     
    </ContentPage>

    This will give the DataGrid the explicit bounds of the page dimensions (you could also point to the ScrollView's size as well)


    Summary

    Ultimately, the DataGrid has it's own ScrollView in which we carefully optimize the item virtualization (vertical and horizontally) so that the DataGrid only renders the items that are visible (and some items slightly off-screen so that scrolling is seamless). 


    If you're still having issues, it would be helpful for us to know what the goal is for this specific page and we might be able to come up with a suitable layout that achieves both goals.

    Regards,
    Lance | Tech Support Engineer, Sr.
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top