jsonmauiobservablecollection

How to Efficiently Load Large JSON Data into ObservableCollection in .NET MAUI?


I'm working on a .NET MAUI application where I need to load a large volume of data from a JSON file and add it to an ObservableCollection. Currently, the application becomes unresponsive during this operation, and the process is slow.

[ObservableProperty]private ObservableCollection<TaskMang> tasks;

private async Task LoadTasksFromExcel(){
var filepath = "C:\\Users\\USER\\Documents\\excel_to_json.json";

if (!File.Exists(filepath))
{
    return;
}

var stopwatch = new Stopwatch();
stopwatch.Start();

try
{
    var jsonString = await File.ReadAllTextAsync(filepath);
    var jsonDocument = JsonDocument.Parse(jsonString);
    var root = jsonDocument.RootElement;

    if (root.TryGetProperty("Task_Master", out JsonElement taskArray))
    {
        // Use IEnumerable for lazy loading
        var tasksEnumerable = taskArray.EnumerateArray().Select(task => new TaskMang
        {
            id = task.GetProperty("TASK_ID").GetInt32(),
            TaskName = task.GetProperty("TASK_NAME").GetString(),
            TaskStartTime = task.GetProperty("START_TIME").GetString(),
            TaskEndTime = task.GetProperty("END_TIME").GetString(),
            TaskTimeTaken = task.GetProperty("TIME_TAKEN").GetString(),
            ProjectName = task.GetProperty("PROJECT_NAME").GetString(),
            SelectedProject = _projectDetailsViewModel.Projects
                .FirstOrDefault(p => p.ProjectName == task.GetProperty("PROJECT_NAME").GetString())
        }).ToList();

        // Add tasks to ObservableCollection in smaller batches
        const int batchSize = 100;
        for (int i = 0; i < tasksEnumerable.Count; i += batchSize)
        {
            var batch = tasksEnumerable.Skip(i).Take(batchSize).ToList();
            Application.Current.Dispatcher.Dispatch(() =>
            {
                foreach (var task in batch)
                {
                    Tasks.Add(task);
                }
            });

            await Task.Delay(10); // Small delay to prevent UI freeze
        }
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}
finally
{
    stopwatch.Stop();
    Console.WriteLine($"Time taken: {stopwatch.ElapsedMilliseconds} ms");
}}

Performance: The application becomes unresponsive during data loading. UI Freezes: Even with batching and small delays, the UI still experiences freezing.

I tried : Batch Updates: Adding items in smaller batches with a delay. Lazy Loading: Using IEnumerable for processing data

Questions: Are there more efficient ways to handle large datasets in an ObservableCollection? Is there a better approach to avoid UI freezes when adding a large number of items? Any tips for optimizing JSON data processing in .NET MAUI?


Solution

  • All you need is to use ObservableRangeCollection and there is method called AddRange. You can find such collection for example here https://github.com/MPowerKit/VirtualizeListView/blob/main/MPowerKit.VirtualizeListView/ObservableRangeCollection.cs

    Note: that under the hood ObservableCollection and thus ObservableRangeCollection stores items in the List<T>, so there is no need to do the batch updates, even more, batching will only decrease your performance.

    What I would do - is to parse json in the background thread and then call AddRange on the collection in the main thread.

    But also you have to keep in mind what UI element is using this collection. If it BindableLayout, then it is unacceptable to use huge data sets there.

    Before fetching and parsing data I would show some loader to the user, that he can understand that smth is happening now and he should wait a bit.