Performance Issues with Fetching Training Days: Seeking Optimization Advice

Custom Code

Hello FlutterFlow Community,

I’m currently working on a feature to generate a calendar with training days fetched from Firestore. The goal is to display a calendar for a given month and mark the days that have training sessions with their info. However, I’m facing performance issues when dealing with a larger number of training days, which makes the process very slow.

Problem:

The performance degrades significantly when fetching around 50 training days from Firestore, leading to slow calendar rendering times. Although the optimized solution I tried using a map for caching improves speed, it still does not fully solve the issue, and it fails to properly identify and mark training days in the calendar.

Here’s the current implementation:

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/backend/schema/structs/index.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

Future<List<CalendarDayStruct>> getCalendarForMonthAction(
  DateTime inputDate,
  List<DocumentReference> trainingDayRefs,
) async {
  List<CalendarDayStruct> calendar = [];
  Map<String, Map<String, dynamic>> trainingDaysMap = {};

  try {
    // Fetch all training days from Firestore and cache them
    for (DocumentReference ref in trainingDayRefs) {
      DocumentSnapshot snapshot = await ref.get();
      if (snapshot.exists) {
        DateTime trainingDate = (snapshot.get('Date') as Timestamp).toDate();
        DocumentReference trainingRef = snapshot.get('TrainingRef');
        List<String> templateDiarioStringList =
            List<String>.from(snapshot.get('TemplateDiarioStringList') ?? []);

        String key = trainingDate.toIso8601String().substring(0, 10);
        trainingDaysMap[key] = {
          'date': trainingDate,
          'trainingRef': trainingRef,
          'templateDiarioStringList': templateDiarioStringList,
          'trainingdayRef': ref,
        };
      }
    }

    // Start by finding the first day of the current month
    DateTime firstOfMonth = DateTime(inputDate.year, inputDate.month, 1);

    // Find the last day of the current month
    DateTime lastOfMonth = DateTime(inputDate.year, inputDate.month + 1, 0);

    // Find the first Monday on or before the first of the month
    DateTime startCalendar =
        firstOfMonth.subtract(Duration(days: firstOfMonth.weekday - 1));

    // Find the last Sunday after the end of the month
    DateTime endCalendar = lastOfMonth.weekday == 7
        ? lastOfMonth
        : lastOfMonth.add(Duration(days: 7 - lastOfMonth.weekday));

    // Populate the calendar using cached training days
    for (DateTime date = startCalendar;
        date.isBefore(endCalendar.add(Duration(days: 1)));
        date = date.add(Duration(days: 1))) {
      bool isPreviousMonth = date.isBefore(firstOfMonth);
      bool isNextMonth = date.isAfter(lastOfMonth);

      DocumentReference? trainingRef;
      DocumentReference? trainingdayRef;
      bool isTrainingDay = false;
      List<String> templateDiarioStringList = [];

      String key = date.toIso8601String().substring(0, 10);
      if (trainingDaysMap.containsKey(key)) {
        var item = trainingDaysMap[key]!;
        isTrainingDay = true;
        trainingRef = item['trainingRef'] as DocumentReference;
        templateDiarioStringList =
            item['templateDiarioStringList'] as List<String>;
        trainingdayRef = item['trainingdayRef'] as DocumentReference;
      }

      CalendarDayStruct dayStruct = CalendarDayStruct(
        calendarDate: date,
        isPreviousMonth: isPreviousMonth,
        isNextMonth: isNextMonth,
        isTrainingDay: isTrainingDay,
        trainingRef: trainingRef,
        teplateDiarioStringList: templateDiarioStringList,
        trainingDayDocRef: trainingdayRef,
      );

      calendar.add(dayStruct);
    }
  } catch (e) {
    print('Error fetching training days: $e');
  }

  return calendar;
}

What have you tried so far?
  • Caching Training Days: Pre-fetched training days and stored them in a map for quick lookup.

  • Optimized Data Fetching: Attempted to reduce the number of database reads and optimize the calendar generation.

I don't know if I have implemented it in a good way anyway.

Did you check FlutterFlow's Documentation for this topic?
No