经过几天的跨线程管理,我得出结论,解决这个问题的最佳方法确实是将计算逻辑移动到cell factory本身,从而在UI线程中完成所有工作。因此,基本上它就像一个魅力:
//Add and remove item when cell is reused for different item
final ChangeListener<T> itemChangedEventHandler = (observable, oldValue, newValue) -> {
synchronized (TrackingListCellFactory.this) {
if (oldValue != null) {
visibleItems.remove(oldValue);
}
if (newValue != null) {
visibleItems.add(newValue);
updateMessengerServiceControlModel(newValue, MessageStatus.MessageStatusEnum.SEEN);
}
}
};
//Update set when bounds of item change
final ChangeListener<Object> boundsChangedHandler = (observable, oldValue, newValue) -> {
synchronized (TrackingListCellFactory.this) {
T item = cell.getItem();
if (item != null) {
visibleItems.add(item);
updateMessengerServiceControlModel(item, MessageStatus.MessageStatusEnum.SEEN);
}
}
};
cell.itemProperty().addListener(itemChangedEventHandler);
//Must update either if cell changes bounds, or if cell moves within scene (e.g. by scrolling):
cell.boundsInLocalProperty().addListener(boundsChangedHandler);
cell.localToSceneTransformProperty().addListener(boundsChangedHandler);
return cell;
IMHO,这是比使用项目索引等更干净和优雅的解决方案。
如果未从另一个线程读取可见项,则可以删除同步块。这将提高工厂性能。