Home > Mobile >  How improve rendering performance in a flutter widget with many text widgets
How improve rendering performance in a flutter widget with many text widgets

Time:12-08

we have a performance problem in our calendar widget. We want to display 3 Years in a scroll view. Each day should be displayed and some days should be marked. The problem is, that the rendering time of this widget is on some devises up to 5 seconds. I think the problem is that we need over 1000 Text widgets to display it. Does someone have an idea how to improve it?

I have written a small sample app. There are many simplifications in it, like every month has 31 days and the layout is bad, but it shows what we want and that it is too slow.

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  bool year = false;

  @override
  Widget build(BuildContext context) {
    const Key currentYearKey = Key('currentYearKey');
    return Scaffold(
        floatingActionButton: FloatingActionButton(
            onPressed: () => setState(() {
                  year = !year;
                })),
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: year
            ? CustomScrollView(
                center: currentYearKey,
                slivers: [
                  SliverToBoxAdapter(
                    child: Column(
                      children: [Year(), Year()],
                    ),
                  ),
                  SliverToBoxAdapter(
                    child: Year(),
                    key: currentYearKey,
                  )
                ],
              )
            : Text("1"));
  }
}

class Year extends StatelessWidget {
  const Year({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Year XX"),
          ...List.generate(
            4,
            (rowIndex) => Row(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisSize: MainAxisSize.min,
              children: List.generate(
                3,
                (columnIndex) {
                  return Expanded(
                      child: Month(
                    daySize: 14,
                    markedDays: [1, 3, 26, 30],
                  ));
                },
              ),
            ),
          ),
        ]);
  }
}

class Month extends StatelessWidget {
  const Month({required this.markedDays, required this.daySize, Key? key})
      : super(key: key);
  final List<int> markedDays;
  final double daySize;

  @override
  Widget build(BuildContext context) {
    return GridView.count(
        padding: EdgeInsets.zero,
        crossAxisCount: 7,
        shrinkWrap: true,
        physics: const NeverScrollableScrollPhysics(),
        children: List.generate(31, (index) {
          final bool isMarked = markedDays.contains(index);
          return Center(
            child: Container(
              height: daySize,
              width: daySize,
              decoration:
                  isMarked ? BoxDecoration(color: Colors.lightBlue) : null,
              child: Text(
                "$index",
                style: isMarked ? TextStyle(fontWeight: FontWeight.bold) : null,
              ),
            ),
          );
        }));
  }
}

We tried to make as much as possible const, it improved it abit, and make it around 30% faster, but we need it much faster. We also tried to replace the GridView in the month through a table or row/column construct, but it does not help.

CodePudding user response:

Instead of columns use ListView.builder, this helped me with long lists: https://docs.flutter.dev/cookbook/lists/long-lists

CodePudding user response:

In this case you defiantly must use GridView.builder / ListView.builder.

This will lead to build widgets on demand. Instead of building everything at once which is Bad practice.

  • Related