状态管理器是连续重建小部件而不是更新,如何消除这种情况?扑

State manager is rebuilding widget continuously instead of on update, how to eliminate this? Flutter

所以我在整理如何将数据动态添加到我的 DataGrid 时遇到了麻烦。我从 Syncfusion 支持那里得到帮助,他们到目前为止表现出色。但是我仍然无法获得完整和正确的功能。

我正在使用 GetX GetBuilder 包装 DataGrid。它从数据库接收数据,并且应该在添加数据库时更新此数据。然而,目前它是连续 运行,或者说每秒 50X。这显然在很多方面都不好。然而,我目前拥有完整的功能,但它不合适。

我将打印语句放入 GridSource 构造函数中,它会连续打印。所以出了点问题,我无法弄清楚。我试过移动构建器(从构建器中移出)以及数据源声明,但这完全破坏了网格加载的功能。

这是完整的演示项目here

有人可以指出我做错了什么吗?

DataGrid 屏幕:

import 'package:flutter/material.dart';
import 'package:getx_hive_demo_one/presentation/event_list_screen/add_event_button.dart';
import 'package:get/get.dart';
import 'package:getx_hive_demo_one/database/database.dart';
import 'package:getx_hive_demo_one/models/event.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

class EventListScreen extends StatelessWidget {
  final Database database = Get.put(Database());

  GridSource dataSource;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Event Dashboard'),
          backgroundColor: Colors.grey[850],
          actions: [AddEventButton(source: dataSource)],
        ),
        body: SafeArea(child: GetBuilder<Database>(
          builder: (database) {
            dataSource = GridSource(database.getEventList());
            return SfDataGrid(
              source: dataSource,
              columnWidthMode: ColumnWidthMode.fill,
              columns: <GridColumn>[
                GridTextColumn(
                    columnName: 'name',
                    label: Container(
                        color: Colors.grey[800],
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Event',
                          style: TextStyle(color: Colors.white),
                        ))),
                GridTextColumn(
                    columnName: 'start',
                    label: Container(
                        color: Colors.grey[800],
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Start Date',
                          style: TextStyle(color: Colors.white),
                        ))),
                GridTextColumn(
                    columnName: 'duration',
                    label: Container(
                        color: Colors.grey[800],
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Event Duration',
                          style: TextStyle(color: Colors.white),
                          overflow: TextOverflow.ellipsis,
                        ))),
                GridTextColumn(
                    columnName: 'invitees',
                    label: Container(
                        color: Colors.grey[800],
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Attendees',
                          style: TextStyle(color: Colors.white),
                        ))),
                GridTextColumn(
                    columnName: 'location',
                    label: Container(
                        color: Colors.grey[800],
                        padding: EdgeInsets.all(8.0),
                        alignment: Alignment.centerLeft,
                        child: Text(
                          'Location',
                          style: TextStyle(color: Colors.white),
                        ))),
              ],
            );
          },
        )));
  }
}

class GridSource extends DataGridSource {
  List<DataGridRow> _eventGridRow = [];
  List<Event> eventGrid = [];

  GridSource(this.eventGrid) {
    print('Run');
    buildDataGridRows();
  }

  void buildDataGridRows() {
    _eventGridRow = eventGrid
        .map<DataGridRow>(
          (event) => DataGridRow(
            cells: [
              DataGridCell<String>(columnName: 'name', value: event.eventName),
              DataGridCell<String>(columnName: 'start', value: event.eventStart.toString()),
              DataGridCell<String>(columnName: 'duration', value: event.eventDuration.toString()),
              DataGridCell<String>(columnName: 'invitees', value: event.numberInvitees.toString()),
              DataGridCell<String>(columnName: 'location', value: event.location),
            ],
          ),
        )
        .toList();
  }

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

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    final int index = _eventGridRow.indexOf(row);
    Color getRowBackgroundColor() {
      if (index % 2 == 0) {
        return Colors.grey[100];
      }
      return Colors.transparent;
    }

    return DataGridRowAdapter(
      color: getRowBackgroundColor(),
      cells: [
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[0].value ?? '',
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[1].value ?? '',
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[2].value ?? '',
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[3].value ?? ' ',
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[4].value ?? '',
            overflow: TextOverflow.ellipsis,
          ),
        ),
      ],
    );
  }

  void updateDataGridSource() {
    notifyListeners();
  }
}

连续打印语句:

flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run
flutter: Run

问题是由于每次都创建 GridSource 以及在 buildDataRow 中调用 getEventList 并刷新,因此循环。请将 DataBase 和 DataGrid 替换为下面提供的代码片段

数据库

import 'package:flutter/foundation.dart';

///
///
/// HIVE DATABASE MODEL USING ENCRYPTION AND CRUD ACTIONS

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:getx_hive_demo_one/models/event.dart';
import 'package:get/get.dart';
import 'package:hive/hive.dart';
import 'dart:convert';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:flutter/material.dart';

class Database extends GetxController {
  GridSource dataGridSource;

  Database() {
    dataGridSource = GridSource(this);
  }

  // Hive box name
  String _boxName = 'database';

  // Initialize our list of contacts
  List<Event> eventList = [];

  // Holds our active contact
  Event _activeEvent;

  ///
  ///
  /// Encrypted Box
  /// Create & open encrypted box
  /// Return encrypted box for other methods to have box
  Future<Box<Event>> encryptedBox() async {
    final FlutterSecureStorage secureStorage = const FlutterSecureStorage();
    var containsEncryptionKey = await secureStorage.containsKey(key: 'key');
    if (!containsEncryptionKey) {
      var key = Hive.generateSecureKey();
      await secureStorage.write(key: 'key', value: base64UrlEncode(key));
    }
    var encryptionKey = base64Url.decode(await secureStorage.read(key: 'key'));
    var box = await Hive.openBox<Event>(_boxName,
        encryptionCipher: HiveAesCipher(encryptionKey));
    return box;
  }

  ///
  ///
  /// Create Event
  /// Saves data to hive box, updates repository & notify listeners
  void addEvent(Event newEvent) async {
    var box = await Hive.openBox<Event>(_boxName);
    await box.add(newEvent);
    eventList = box.values.toList();
    refresh();
  }

  ///
  ///
  /// Read Event
  /// Sends events in database to list repository
  void getEvents() async {
    var box = await Hive.openBox<Event>(_boxName);
    eventList = box.values.toList();
    refresh();
  }

  ///
  ///
  /// Read Event
  /// Returns event list
  List<Event> getEventList() {
    getEvents();
    return eventList;
  }

  ///
  ///
  /// Read Event
  /// Gets contact by index from repository
  Event getEvent(index) {
    return eventList[index];
  }

  ///
  ///
  /// Read Event
  /// Gets length of event repository
  int get eventCount {
    return eventList.length;
  }

  ///
  ///
  /// Read Event
  /// Sets active event to notify listeners for
  void setActiveEvent(key) async {
    var box = await Hive.openBox<Event>(_boxName);
    _activeEvent = box.get(key);
    refresh();
  }

  ///
  ///
  /// Read Event
  /// Get active event
  Event getActiveEvent() {
    return _activeEvent;
  }

  ///
  ///
  /// Update Event
  /// Updates event info with new data
  void editEvent({Event event, int eventKey}) async {
    var box = await Hive.openBox<Event>(_boxName);
    await box.put(eventKey, event);
    eventList = box.values.toList();
    _activeEvent = box.get(eventKey);
    refresh();
  }

  void deleteAll() async{
    var box = await Hive.openBox<Event>(_boxName);
    box.deleteFromDisk();
    refresh();
  }

  ///
  ///
  /// Delete Event
  /// Deletes event from box and updates list
  void deleteEvent(key) async {
    var box = await Hive.openBox<Event>(_boxName);
    await box.delete(key);
    eventList = box.values.toList();
    print('Deleted event at:' + key.toString());
    refresh();
  }

  /// Non-encrypted box
  /// var box = await Hive.openBox<Event>(_boxName);
}

class GridSource extends DataGridSource {


List<DataGridRow> _eventGridRow = [];
  final Database database;
  List eventList = [];

  GridSource(this.database) {
    this.database.addListener(handleListChanges);
  }

  void handleListChanges() {
    if (!listEquals(eventList, this.database.eventList)) {
      eventList = this.database.eventList;
      buildDataGridRows();
      notifyListeners();
    }
  }

  void buildDataGridRows() {
    _eventGridRow = eventList
        .map<DataGridRow>(
          (event) => DataGridRow(
            cells: [
              DataGridCell<String>(columnName: 'name', value: event.eventName),
              DataGridCell<String>(
                  columnName: 'start', value: event.eventStart.toString()),
              DataGridCell<String>(
                  columnName: 'duration',
                  value: event.eventDuration.toString()),
              DataGridCell<String>(
                  columnName: 'invitees',
                  value: event.numberInvitees.toString()),
              DataGridCell<String>(
                  columnName: 'location', value: event.location),
            ],
          ),
        )
        .toList();
  }

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

  @override
  DataGridRowAdapter buildRow(DataGridRow row) {
    final int index = _eventGridRow.indexOf(row);
    Color getRowBackgroundColor() {
      if (index % 2 == 0) {
        return Colors.grey[100];
      }
      return Colors.transparent;
    }

    return DataGridRowAdapter(
      color: getRowBackgroundColor(),
      cells: [
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[0].value,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[1].value,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[2].value,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[3].value,
            overflow: TextOverflow.ellipsis,
          ),
        ),
        Container(
          alignment: Alignment.centerLeft,
          padding: EdgeInsets.all(8.0),
          child: Text(
            row.getCells()[4].value,
            overflow: TextOverflow.ellipsis,
          ),
        ),
      ],
    );
  }
}

DataGridPage

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:getx_hive_demo_one/database/database.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';

class DataGrid extends StatelessWidget {
  final Database database = Get.put(Database());


  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          body: GetBuilder<Database>(
              builder: (database) {
                return SfDataGrid(
                  source: database.dataGridSource,
                  columnWidthMode: ColumnWidthMode.fill,
                  columns: <GridColumn>[
                    GridTextColumn(
                        columnName: 'name',
                        label: Container(
                            color: Colors.grey[800],
                            padding: EdgeInsets.all(8.0),
                            alignment: Alignment.centerLeft,
                            child: Text(
                              'Event',
                              style: TextStyle(color: Colors.white),
                            ))),
                    GridTextColumn(
                        columnName: 'start',
                        label: Container(
                            color: Colors.grey[800],
                            padding: EdgeInsets.all(8.0),
                            alignment: Alignment.centerLeft,
                            child: Text(
                              'Start Date',
                              style: TextStyle(color: Colors.white),
                            ))),
                    GridTextColumn(
                        columnName: 'duration',
                        label: Container(
                            color: Colors.grey[800],
                            padding: EdgeInsets.all(8.0),
                            alignment: Alignment.centerLeft,
                            child: Text(
                              'Event Duration',
                              style: TextStyle(color: Colors.white),
                              overflow: TextOverflow.ellipsis,
                            ))),
                    GridTextColumn(
                        columnName: 'invitees',
                        label: Container(
                            color: Colors.grey[800],
                            padding: EdgeInsets.all(8.0),
                            alignment: Alignment.centerLeft,
                            child: Text(
                              'Attendees',
                              style: TextStyle(color: Colors.white),
                            ))),
                    GridTextColumn(
                        columnName: 'location',
                        label: Container(
                            color: Colors.grey[800],
                            padding: EdgeInsets.all(8.0),
                            alignment: Alignment.centerLeft,
                            child: Text(
                              'Location',
                              style: TextStyle(color: Colors.white),
                            ))),
                  ],
                );
              })),
    );
  }
}