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

[syncfusion_flutter_datagrid] Performance is terrible when use setState with SfDataPaper #1721

Closed
Trung15010802 opened this issue Mar 8, 2024 · 7 comments
Labels
bug Something isn't working data grid Data grid component follow-up scheduled Follow-up scheduled

Comments

@Trung15010802
Copy link

I am using syncfusion_flutter_datagrid: ^24.2.9, if i use checkbox the performance is very bad:

Without checkbox:
The scroll and animation is very smooth

with_checkbox.mp4

With checkbox:
The scroll is delayed and animation isn't smooth

with_checkbox_2.mp4
@VijayakumarMariappan VijayakumarMariappan added data grid Data grid component open Open labels Mar 12, 2024
@Tamilarasan-Paranthaman

Hi @Trung15010802,

Based on the provided details, we have created a basic DataGrid sample and thoroughly tested it on our end. Regrettably, we were unable to replicate the reported scrolling performance issue, even when enabling checkboxes in the DataGrid.

We have attached the sample that we used for testing to this ticket for your reference. We kindly request that you review the attached sample and execute it on your end. Should any configurations or adjustments be necessary to accurately reproduce the issue, please modify the sample accordingly. Additionally, we would appreciate detailed steps for reproducing the issue along with the sample, as well as any other pertinent details.

Sample
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

void main() {
  runApp(const MaterialApp(home: MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: false),
      home: const SfDataGridDemo(),
    );
  }
}

class SfDataGridDemo extends StatefulWidget {
  const SfDataGridDemo({super.key});

  @override
  SfDataGridDemoState createState() => SfDataGridDemoState();
}

class SfDataGridDemoState extends State<SfDataGridDemo> {
  List<Employee> _employees = <Employee>[];
  late EmployeeDataSource _employeeDataSource;

  @override
  void initState() {
    super.initState();
    _employees = getEmployeeData();
    _employeeDataSource = EmployeeDataSource(_employees);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
        body: SfDataGrid(
          source: _employeeDataSource,
          columns: getColumns,
          selectionMode: SelectionMode.multiple,
          showCheckboxColumn: true,
        ));
  }

  List<GridColumn> get getColumns {
    return <GridColumn>[
      GridColumn(
          columnName: 'ID',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('ID'))),
      GridColumn(
          columnName: 'Name',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Name'))),
      GridColumn(
          columnName: 'Designation',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child:
                  const Text('Designation', overflow: TextOverflow.ellipsis))),
      GridColumn(
          columnName: 'Salary',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Salary'))),
    ];
  }

  List<Employee> getEmployeeData() {
    return [
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
    ];
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource(List<Employee> employees) {
    buildDataGridRows(employees);
  }

  List<DataGridRow> datagridRows = [];

  @override
  List<DataGridRow> get rows => datagridRows;

  void buildDataGridRows(List<Employee> employeesData) {
    datagridRows = employeesData
        .map<DataGridRow>((e) => DataGridRow(cells: [
              DataGridCell<int>(columnName: 'ID', value: e.id),
              DataGridCell<String>(columnName: 'Name', value: e.name),
              DataGridCell<String>(
                  columnName: 'Designation', value: e.designation),
              DataGridCell<int>(columnName: 'Salary', value: e.salary),
            ]))
        .toList();
  }

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((dataGridCell) {
      return Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.symmetric(horizontal: 8.0),
        child: Text(dataGridCell.value.toString()),
      );
    }).toList());
  }
}

class Employee {
  Employee(this.id, this.name, this.designation, this.salary);
  final int id;
  final String name;
  final String designation;
  final int salary;
}
Output
Recording.2024-03-12.160112.mp4

Regards,
Tamilarasan

@ashok-kuvaraja ashok-kuvaraja added waiting for customer response Cannot make further progress until the customer responds. and removed open Open labels Mar 12, 2024
@Trung15010802
Copy link
Author

Trung15010802 commented Mar 19, 2024

Hi @Tamilarasan-Paranthaman, Thank for your response
I've edited your sample code to recreate the error:

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

void main() {
  runApp(const MaterialApp(home: MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: false),
      home: const SfDataGridDemo(),
    );
  }
}

class SfDataGridDemo extends StatefulWidget {
  const SfDataGridDemo({super.key});

  @override
  SfDataGridDemoState createState() => SfDataGridDemoState();
}

class SfDataGridDemoState extends State<SfDataGridDemo> {
  List<Employee> _employees = <Employee>[];
  late EmployeeDataSource _employeeDataSource;

  @override
  void initState() {
    super.initState();
    _employees = getEmployeeData();
    _employeeDataSource = EmployeeDataSource(_employees);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')),
      body: Column(
        children: [
          Expanded(
            child: SfDataGrid(
              source: _employeeDataSource,
              columns: getColumns,
              selectionMode: SelectionMode.multiple,
              showCheckboxColumn: true,
            ),
          ),
          SfDataPager(
            pageCount: 1,
            delegate: _employeeDataSource,
            onPageNavigationEnd: (pageIndex) {
              debugPrint('onPageNavigationEnd: $pageIndex');
              setState(() {});
            },
          )
        ],
      ),
    );
  }

  List<GridColumn> get getColumns {
    return <GridColumn>[
      GridColumn(
          columnWidthMode: ColumnWidthMode.fill,
          columnName: 'ID',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('ID'))),
      GridColumn(
          columnWidthMode: ColumnWidthMode.fill,
          columnName: 'Name',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Name'))),
      GridColumn(
          columnWidthMode: ColumnWidthMode.fill,
          columnName: 'Designation',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child:
                  const Text('Designation', overflow: TextOverflow.ellipsis))),
      GridColumn(
          columnWidthMode: ColumnWidthMode.fill,
          columnName: 'Salary',
          label: Container(
              padding: const EdgeInsets.all(8.0),
              alignment: Alignment.center,
              child: const Text('Salary'))),
    ];
  }

  List<Employee> getEmployeeData() {
    return [
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
      Employee(10001, 'Jack', 'Manager', 150000),
      Employee(10002, 'Perry', 'Project Lead', 80000),
      Employee(10003, 'James', 'Developer', 55000),
      Employee(10004, 'Michael', 'Designer', 39000),
      Employee(10005, 'Roland Mendel', 'Developer', 45000),
      Employee(10006, 'Sven Ottlieb', 'UI Designer', 36000),
      Employee(10007, 'Williams', 'Developer', 44000),
      Employee(10008, 'Adams', 'Developer', 43000),
      Employee(10009, 'Edwards', 'QA Testing', 43000),
      Employee(10010, 'Grimes', 'Developer', 43000),
      Employee(10011, 'Maria Andres', 'Developer', 41000),
      Employee(10012, 'Thomas Hardy', 'Developer', 40000),
      Employee(10013, 'Hanna Moos', 'Sales Associate', 350000),
      Employee(10014, 'Elizabeth', 'Developer', 41000),
      Employee(10015, 'Patricio Simpson', 'Administrator', 33000),
      Employee(10016, 'Francisco Chang', 'Developer', 32000),
      Employee(10017, 'Yang Wang', 'Developer', 30000),
      Employee(10018, 'Peter Franken', 'Developer', 30000),
      Employee(10019, 'Carlos Schmitt', 'Developer', 30000),
      Employee(10020, 'Yoshi Latimer', 'Developer', 28000),
    ];
  }
}

class EmployeeDataSource extends DataGridSource {
  EmployeeDataSource(List<Employee> employees) {
    buildDataGridRows(employees);
  }

  List<DataGridRow> datagridRows = [];

  @override
  List<DataGridRow> get rows => datagridRows;

  void buildDataGridRows(List<Employee> employeesData) {
    datagridRows = employeesData
        .map<DataGridRow>((e) => DataGridRow(cells: [
              DataGridCell<int>(columnName: 'ID', value: e.id),
              DataGridCell<String>(columnName: 'Name', value: e.name),
              DataGridCell<String>(
                  columnName: 'Designation', value: e.designation),
              DataGridCell<int>(columnName: 'Salary', value: e.salary),
            ]))
        .toList();
  }

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((dataGridCell) {
      return Container(
        alignment: Alignment.center,
        padding: const EdgeInsets.symmetric(horizontal: 8.0),
        child: Text(dataGridCell.value.toString()),
      );
    }).toList());
  }
}

class Employee {
  Employee(this.id, this.name, this.designation, this.salary);
  final int id;
  final String name;
  final String designation;
  final int salary;
}

The cause of this problem is the method onPageNavigationEnd is trigger when SfDataGrid is built . So if i call setState. It will cause rebuild multiple time:

I believe it's a bug about SfDataPager not checkbox.
image

@abineshPalanisamy
Copy link

Hi @Trung15010802 ,

Thank you for providing the sample. Following our testing, we have confirmed that this is indeed a bug. A bug report has been logged in our feedback portal to address this issue. We are committed to resolving the reported issue and will incorporate the necessary changes in the upcoming weekly patch release, scheduled for rollout on April 02, 2024. We will let you know once released. We appreciate your patience and understanding until then.

Regards,
Abinesh P

@ashok-kuvaraja ashok-kuvaraja added bug Something isn't working follow-up scheduled Follow-up scheduled and removed waiting for customer response Cannot make further progress until the customer responds. labels Mar 21, 2024
@Trung15010802 Trung15010802 changed the title [syncfusion_flutter_datagrid] Performance is terrible when enable checkbox [syncfusion_flutter_datagrid] Performance is terrible when use setState with SfDataPaper Mar 22, 2024
@abineshPalanisamy
Copy link

Hi @Trung15010802 ,

We are glad to inform you that the reported problem has been resolved on our end. Therefore, kindly update SfDataGrid to the latest version. If you have any further queries, please don't hesitate to reach out. We are more than happy to assist you.

Regards,
Abinesh P

@Trung15010802
Copy link
Author

Hi @abineshPalanisamy,
I realized that the issue hasn't been resolved. Tested on latest version
image

@Trung15010802 Trung15010802 reopened this Apr 12, 2024
@Trung15010802
Copy link
Author

And next page button not trigger onPageNavigationStart function, previous page not trigger onPageNavigationEnd
image

@abineshPalanisamy
Copy link

Hi @Trung15010802,

Based on the information provided, the issue mentioned is that performance is terrible when using setState with SfDataPager. This unintended call to the paging callbacks results in multiple setState triggers, causing the SfDataPager to rebuild each time setState is invoked. Therefore, we have restricted unwanted calls without requiring page navigation. During the initial loading phase, we allow callbacks to be made, this is the expected behavior of pagination callbacks. Kindly check whether the performance stabilizes after restricting the SfDataPager from rebuilding each time setState is invoked.

We are investigating the issue where the next and previous page buttons do not trigger page callbacks. In the meantime, we will provide further details.

If you are still encountering the performance problem, we kindly ask you to provide any additional clear details regarding the performance issue when using SfDataPager. This additional information will greatly aid us in further investigating the matter and delivering an appropriate solution as promptly as possible.

Regards,
Abinesh P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working data grid Data grid component follow-up scheduled Follow-up scheduled
Projects
None yet
Development

No branches or pull requests

5 participants