The following setup is what I have and it describes a nesting of UI elements into a graph with growing complexity:
public class BuildingListView extends ListView<Building> {
...
//herein defines a BuildingCellFactory for this ListView's cells
...
}
public class BuildingCell extends ListCell<Building> {
GridPane customGridPane= new CustomGridPane();
WorkerTable workerTable = new WorkerTable();
...
@Override
protected void updateItem(final Building building, final boolean isEmpty) {
...
this.workerTable.setItems(building.getWorkers());
}
}
public class WorkerTable extends TableView<Worker> {
...
//with its own cell factory with nested UI components, tables, lists, accordions
}
I find that when the top-level BuildingListView changes sort order, or is scrolled, various cells at all levels don't actually seem to be re-used and I have what seems to be LOTS and LOTS of UI components at all levels of the graph being allocated and de-allocated by various UI interactions. It seems extremely wasteful.
During a given execution I may have 10 buildings with 10-30 workers each and maybe 40 UI elements per worker, which if it were all just created and kept in memory would translate to roughly 6,000 to 16,000 total UI components. However, scrolling around and using the software over the course of half an hour actually results in millions of allocations and de-allocations.
It makes me want to create caches of these instances and re-use them manually, but it seems like JavaFX should be doing that for me under the hood (but doesn't seem to be).
Am I doing something wrong? Is there another way to structure my UI component construction work outside of these "updateItem" methods so that those are strictly for setting values in the UI components rather than instantiating entire graphs of objects as the UI is used?
I've tried the above setup, and my expectation is that there would be a maximum of maybe 20 instances of BuildingCell ever instantiated, but in practice there are many more and the instantiations increase over time.