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] DataGridSource was used after being disposed with SfDataPager #1803

Closed
Trung15010802 opened this issue Apr 14, 2024 · 2 comments
Labels
bug Something isn't working data grid Data grid component open Open waiting for customer response Cannot make further progress until the customer responds.

Comments

@Trung15010802
Copy link

If I dispose a DataGridSource with SfDataPager (to avoid memory leak). I got this error:

══╡ EXCEPTION CAUGHT BY SCHEDULER LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during a scheduler callback:
A EmployeeDataSource was used after being disposed.
Once you have called dispose() on a EmployeeDataSource, it can no longer be used.

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3       throw_
packages/flutter/src/foundation/change_notifier.dart 179:9                        <fn>
packages/flutter/src/foundation/change_notifier.dart 185:14                       debugAssertNotDisposed
packages/flutter/src/foundation/change_notifier.dart 412:27                       notifyListeners
packages/syncfusion_flutter_datagrid/src/datagrid_widget/sfdatagrid.dart 4843:11  notifyListeners
packages/syncfusion_flutter_datagrid/src/datagrid_widget/sfdatagrid.dart 4921:13  <fn>
packages/flutter/src/scheduler/binding.dart 1386:7                                [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1322:11                               handleDrawFrame
packages/flutter/src/scheduler/binding.dart 1169:5                                [_handleDrawFrame]
lib/_engine/engine/platform_dispatcher.dart 1346:5                                invoke
lib/_engine/engine/platform_dispatcher.dart 260:5                                 invokeOnDrawFrame
lib/_engine/engine/initialization.dart 185:36                                     <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 550:37  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 555:39  dcall

This is my code:

class MyHomePage extends ConsumerStatefulWidget {
  const MyHomePage({super.key});

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

class _MyHomePageState extends ConsumerState<MyHomePage> {
  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    final List<Widget> list = [const TableWithPaper(), const Placeholder()];

    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: const Text('Home page'),
          bottom: TabBar(
            onTap: (value) {
              setState(() {
                _currentIndex = value;
              });
            },
            tabs: const [
              Tab(
                text: '1',
              ),
              Tab(
                text: '2',
              ),
            ],
          ),
        ),
        body: list[_currentIndex],
      ),
    );
  }
}

/// The home page of the application which hosts the datagrid.
class TableWithPaper extends StatefulWidget {
  /// Creates the home page.
  const TableWithPaper({Key? key}) : super(key: key);

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

class TableWithPaperState extends State<TableWithPaper> {
  List<Employee> employees = <Employee>[];
  late EmployeeDataSource employeeDataSource;

  @override
  void initState() {
    super.initState();
    employees = getEmployeeData();
    employeeDataSource = EmployeeDataSource(employeeData: employees);
  }

  @override
  void dispose() {
    employeeDataSource.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Syncfusion Flutter DataGrid'),
      ),
      body: Column(
        children: [
          Expanded(
            child: SfDataGrid(
              source: employeeDataSource,
              columnWidthMode: ColumnWidthMode.fill,
              rowsPerPage: 10,
              columns: <GridColumn>[
                GridColumn(
                    columnName: 'id',
                    label: Container(
                        padding: EdgeInsets.all(16.0),
                        alignment: Alignment.center,
                        child: Text(
                          'ID',
                        ))),
                GridColumn(
                    columnName: 'name',
                    label: Container(
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: Text('Name'))),
                GridColumn(
                    columnName: 'designation',
                    label: Container(
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: Text(
                          'Designation',
                          overflow: TextOverflow.ellipsis,
                        ))),
                GridColumn(
                    columnName: 'salary',
                    label: Container(
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.center,
                        child: Text('Salary'))),
              ],
            ),
          ),
          SfDataPager(
            delegate: employeeDataSource,
            pageCount: employeeDataSource._employeeData.length / 10,
            direction: Axis.horizontal,
          )
        ],
      ),
    );
  }

  List<Employee> getEmployeeData() {
    return [
      Employee(10001, 'James', 'Project Lead', 20000),
      Employee(10002, 'Kathryn', 'Manager', 30000),
      Employee(10003, 'Lara', 'Developer', 15000),
      Employee(10004, 'Michael', 'Designer', 15000),
      Employee(10005, 'Martin', 'Developer', 15000),
      Employee(10006, 'Newberry', 'Developer', 15000),
      Employee(10007, 'Balnc', 'Developer', 15000),
      Employee(10008, 'Perry', 'Developer', 15000),
      Employee(10009, 'Gable', 'Developer', 15000),
      Employee(10010, 'Grimes', 'Developer', 15000)
    ];
  }
}

/// Custom business object class which contains properties to hold the detailed
/// information about the employee which will be rendered in datagrid.
class Employee {
  /// Creates the employee class with required details.
  Employee(this.id, this.name, this.designation, this.salary);

  /// Id of an employee.
  final int id;

  /// Name of an employee.
  final String name;

  /// Designation of an employee.
  final String designation;

  /// Salary of an employee.
  final int salary;
}

/// An object to set the employee collection data source to the datagrid. This
/// is used to map the employee data to the datagrid widget.
class EmployeeDataSource extends DataGridSource {
  /// Creates the employee data source class with required details.
  EmployeeDataSource({required List<Employee> employeeData}) {
    _employeeData = employeeData
        .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();
  }

  List<DataGridRow> _employeeData = [];

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

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((e) {
      return Container(
        alignment: Alignment.center,
        padding: EdgeInsets.all(8.0),
        child: Text(e.value.toString()),
      );
    }).toList());
  }
}
@VijayakumarMariappan VijayakumarMariappan added data grid Data grid component open Open labels Apr 15, 2024
@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 30, 2024. We will let you know once released. We appreciate your patience and understanding until then.

Regards,
Abinesh P

@ashok-kuvaraja ashok-kuvaraja added follow-up scheduled Follow-up scheduled bug Something isn't working labels Apr 16, 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(25.1.42). If you have any further queries, please don't hesitate to reach out. We are more than happy to assist you.

Regards,
Abinesh P

@ashok-kuvaraja ashok-kuvaraja added waiting for customer response Cannot make further progress until the customer responds. and removed follow-up scheduled Follow-up scheduled labels Apr 30, 2024
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 open Open waiting for customer response Cannot make further progress until the customer responds.
Projects
None yet
Development

No branches or pull requests

4 participants