使用NatTable分组功能时出现NullPointerException问题咨询
NatTable GroupBy分组功能NullPointerException问题解答
问题描述
使用NatTable的GroupBy分组功能时,偶尔会在绘制事件中触发如下NullPointerException:
java.lang.NullPointerException: Cannot read field "left" because "node" is null at ca.odell.glazedlists.impl.adt.barcode2.FourColorTree.get(FourColorTree.java:169) at ca.odell.glazedlists.TreeList.getTreeNode(TreeList.java:303) at ca.odell.glazedlists.TreeList.get(TreeList.java:288) at org.eclipse.nebula.widgets.nattable.data.ListDataProvider.getRowObject(ListDataProvider.java:64) at pml.rcp.ui.table.CellTableHintAdapter.accumulateConfigLabels(CellTableHintAdapter.java:39)
- 先拖拽表头对第一列显式排序后再调用分组功能(相同数据),不会触发异常;
- 调用
natTable.doCommand(new TreeCollapseAllCommand());时也会触发相同异常; - 已知Glazed Lists的FourColorTree存在相关问题报告,疑似竞态条件导致,且该类标注为原型版本,已使用最新版Glazed Lists(1.11.0);
- 问题难以复现,NatTable官方示例运行正常。
问题解答
1. 是否为已知问题?有无已知解决方案?
这是Glazed Lists中FourColorTree的已知问题,该类作为原型实现,本身存在线程安全缺陷,容易在并发操作(比如UI绘制时后台数据变更、分组/折叠操作与数据更新交叉)时触发空指针。
可尝试的解决方案:
- 确保操作线程安全:所有对Glazed Lists数据模型(包括TreeList、GroupByList)的修改操作,都必须在UI线程执行,避免后台线程直接修改数据。NatTable和Glazed Lists的联动依赖UI线程的事件调度,跨线程操作极易引发竞态条件。
- 替换TreeList模型实现:创建TreeList时,指定使用
BasicTreeListModel替代默认的FourColorTree实现,代码示例:TreeList<E> treeList = new TreeList<>(sourceList, TreeList.nodesStartExpanded(), new BasicTreeListModel<>()); - 添加临时防御逻辑:在自定义的
CellTableHintAdapter.accumulateConfigLabels方法中,先判断getRowObject返回值是否为null,避免后续操作触发异常:Object rowObject = dataProvider.getRowObject(rowIndex); if (rowObject == null) { return; } // 原有业务逻辑 - 尝试快照版本修复:部分Glazed Lists快照版本对FourColorTree的空指针问题有修复,若项目允许使用快照包可尝试升级。
2. 是否可以更换底层算法?(比如不使用Glazed Lists或至少不使用FourColorTree类)
完全可以更换:
- 替换FourColorTree:无需抛弃Glazed Lists,直接使用自带的
BasicTreeListModel替代即可,该模型基于传统树形结构实现,稳定性更好,仅在大数据量场景下性能略逊于FourColorTree,足以覆盖多数业务需求。 - 完全不使用Glazed Lists:NatTable支持自定义数据提供器,可基于普通
List自行实现分组逻辑,配合NatTable的GroupByDataLayer及相关命令完成分组、展开/折叠等功能,但需要自行处理数据聚合、状态维护等逻辑,开发量相对较大。
内容的提问来源于stack exchange,提问作者Chris Lewold
相关产品推荐
相关产品推荐

