如何优化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
相关产品推荐
相关产品推荐

