You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化PlutoGrid在多列场景下的表格渲染性能?

PlutoGrid 渲染性能优化问题

我在开发Flutter项目时,使用PlutoGrid组件展示案件数据表,数据来源于存储案件信息(如眼睛自然颜色、失踪日期等)的映射列表。目前仅2-3行数据时,渲染就十分缓慢,但实际业务会涉及大量列,因此担忧后续性能表现。以下是我的代码片段:

class WebCaseList extends StatelessWidget {
  final List<Map<String, dynamic>> caseList;

  WebCaseList({required this.caseList});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(right: 20.0, top: 20, left: 20),
      child: PlutoGrid(
        columns: _buildColumns(),
        rows: _buildRows(),
        mode: PlutoGridMode.readOnly,
        onChanged: (PlutoGridOnChangedEvent event) {},
        configuration: PlutoGridConfiguration(
          style: PlutoGridStyleConfig(
            menuBackgroundColor: Color.fromRGBO(43, 58, 85, 1),
            rowHeight: 70,
            defaultColumnTitlePadding: EdgeInsets.only(left: 20),
            enableCellBorderHorizontal: true,
            gridBorderRadius: BorderRadius.circular(8),
            gridBorderColor: Color(0xFFE2E9EA),
            enableGridBorderShadow: true,
            enableCellBorderVertical: false,
          ),
          columnSize: const PlutoGridColumnSizeConfig(
              autoSizeMode: PlutoAutoSizeMode.scale,
              resizeMode: PlutoResizeMode.normal),
          scrollbar: PlutoGridScrollbarConfig(
            scrollbarThickness: 8,
            scrollbarRadius: Radius.circular(8),
            scrollBarColor: Color(0XFF40038D),
          ),
        ),
      ),
    );
  }

  List<PlutoColumn> _buildColumns() {
    return [
      PlutoColumn(
          title: 'Eye Natural Color',
          field: 'eyeNaturalColor',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Missing Date',
          field: 'missingDate',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Sex',
          field: 'sex',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Case Number',
          field: 'caseNumber',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Case Manager',
          field: 'caseManager',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'First Name',
          field: 'firstName',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Middle Name',
          field: 'middleName',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Last Name',
          field: 'lastName',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Case Type',
          field: 'caseType',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Request Type',
          field: 'requestType',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'City',
          field: 'city',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'ZIP',
          field: 'zip',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'State',
          field: 'state',
          type: PlutoColumnType.text(),
          minWidth: 150),
      PlutoColumn(
          title: 'Country',
          field: 'country',
          type: PlutoColumnType.text(),
          minWidth: 150),
    ];
  }

  List<PlutoRow> _buildRows() {
    return caseList.map((caseItem) {
      return PlutoRow(cells: {
        'eyeNaturalColor': PlutoCell(value: caseItem['eyeNaturalColor'] ?? ''),
        'sex': PlutoCell(value: caseItem['sex'] ?? ''),
        'missingDate': PlutoCell(value: caseItem['missingDate'] ?? ''),
        'caseNumber': PlutoCell(value: caseItem['caseNumber'] ?? ''),
        'caseManager': PlutoCell(value: caseItem['caseManager'] ?? ''),
        'firstName': PlutoCell(value: caseItem['firstName'] ?? ''),
        'middleName': PlutoCell(value: caseItem['middleName'] ?? ''),
        'lastName': PlutoCell(value: caseItem['lastName'] ?? ''),
        'caseType': PlutoCell(value: caseItem['caseType'] ?? ''),
        'requestType': PlutoCell(value: caseItem['requestType'] ?? ''),
        'city': PlutoCell(value: caseItem['city'] ?? ''),
        'zip': PlutoCell(value: caseItem['zip'] ?? ''),
        'state': PlutoCell(value: caseItem['state'] ?? ''),
        'country': PlutoCell(value: caseItem['country'] ?? ''),
      });
    }).toList();
  }
}
优化方案
  • 缓存列和行数据,避免重复创建:当前每次build都会重新调用_buildColumns()和_buildRows()生成新列表,可在构造函数中初始化并缓存,减少重复计算:

    class WebCaseList extends StatelessWidget {
      final List<Map<String, dynamic>> caseList;
      late final List<PlutoColumn> _columns;
      late final List<PlutoRow> _rows;
    
      WebCaseList({required this.caseList}) {
        _columns = _buildColumns();
        _rows = _buildRows();
      }
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.only(right: 20.0, top: 20, left: 20),
          child: PlutoGrid(
            columns: _columns, // 直接用缓存的列
            rows: _rows, // 直接用缓存的行
            // ... 其余配置不变
          ),
        );
      }
    
      // _buildColumns和_buildRows方法保持不变
    }
    
  • 调整列尺寸计算模式:PlutoAutoSizeMode.scale会让列自动缩放适配容器,大量列时会增加布局计算开销,建议改为PlutoAutoSizeMode.none,让列支持横向滚动,降低布局压力:

    columnSize: const PlutoGridColumnSizeConfig(
        autoSizeMode: PlutoAutoSizeMode.none,
        resizeMode: PlutoResizeMode.normal),
    
  • 精简样式配置,减少绘制开销:

    • 关闭非必要的enableGridBorderShadow,阴影绘制会增加GPU负载;
    • 适当降低rowHeight,过高的行高会增加单页渲染的组件数量;
    • 对于固定的样式参数,尽量用const修饰,减少对象重建。
  • 提前处理数据源空值:把caseItem[key] ?? ''的空值处理逻辑移到数据源层面,在传入WebCaseList前统一处理,避免在生成PlutoRow时逐个判断,减少初始化开销。

  • 启用分页/懒加载:后续数据量增大后,不要一次性加载所有行,实现分页加载逻辑,只渲染当前页面的行数据,大幅减少渲染组件数量。

  • 使用const构造函数优化配置:将PlutoGridScrollbarConfig等不变的配置改为const,避免每次build都创建新对象:

    scrollbar: const PlutoGridScrollbarConfig(
      scrollbarThickness: 8,
      scrollbarRadius: Radius.circular(8),
      scrollBarColor: Color(0XFF40038D),
    ),
    

内容的提问来源于stack exchange,提问作者poonamtomar34

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:04:59