Reputation: 604
I have a huge JavaFX application that mostly uses FXML files to create the views, i noticed high memory usage but have been ignoring it for a while. After investigation i found that every single view is consuming a lot, however, after closing the form garbage collector does the job and used memory is released. For example, scrolling throw a table view that has approx. 1000 elements [screen shot attached], the memory usage spikes from 350 MB to 780 MB,,
The exact same happens on scrolling throw a list view that shows the same data of the table view :
the question is,, is that normal? or i maybe doing something wrong
UPDATE
For table view i am doing the following to generate a column:
public static <T> TableColumn<T, T> generateGraphicColumn(String title, Callback<TableColumn<T, T>, TableCell<T, T>> callback) {
TableColumn<T, T> column = generateColumn(title, null);
column.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<T, T>, ObservableValue<T>>() {
@Override
public ObservableValue<T> call(CellDataFeatures<T, T> param) {
SimpleObjectProperty<T> s = new SimpleObjectProperty<>();
s.setValue(param.getValue());
return s;
}
});
column.setCellFactory(callback);
return column;
}
public static <T> TableColumn<T, T> generateGraphicColumn(String title, Callback<TableColumn<T, T>, TableCell<T, T>> callback, double width) {
TableColumn<T, T> column = generateGraphicColumn(title, callback);
column.setMaxWidth(width);
column.setMinWidth(width);
return column;
}
public static <T,S> TableColumn<T, S> generateColumn(String title,
Callback<TableColumn.CellDataFeatures<T, S>, ObservableValue<S>> propertyValueFactory) {
TableColumn<T, S> column;
column = new TableColumn<>();
if (propertyValueFactory != null)
column.setCellValueFactory(propertyValueFactory);
column.setStyle(column.getStyle() + "-fx-alignment: BASELINE_CENTER;");
column.setText(title);
return column;
}
and i am using code above as following:
{ // status
TableColumn<Visit, Visit> column = TableViewUtilities.generateGraphicColumn(text("General.STATUS"),
new Callback<TableColumn<Visit, Visit>, TableCell<Visit, Visit>>() {
@Override
public TableCell<Visit, Visit> call(final TableColumn<Visit, Visit> param) {
final TableCell<Visit, Visit> cell = new TableCell<Visit, Visit>() {
@Override
public void updateItem(Visit item, boolean empty) {
super.updateItem(item, empty);
if (empty || getIndex() < 0) {
setGraphic(null);
setText(null);
return;
}
item = getTableView().getItems().get(getIndex());
Label label = new Label();
StackPane pane = new StackPane(label);
pane.setAlignment(Pos.CENTER);
label.setMaxWidth(10);
label.setMinWidth(10);
label.setMinHeight(30);
setText(item.getStatus().display());
String background = FXMLConstants .toHexString(ColorUtils.getVisitBackgroundColor(item));
pane.setStyle(String.format("-fx-background-color:%s;;", background));
setGraphic(pane);
setText(item.getStatus().display());
setStyle(getStyle() + "-fx-alignment: CENTER_LEFT;");
}
};
return cell;
}
}, 100);
column.setComparator(VisitCommonHelper.getCompByStatus());
tblVisits.getColumns().add(column);
}
Upvotes: 1
Views: 2645
Reputation: 6911
You are creating a new Label
and StackPane
for every non-empty cell update, which may explain why the heap usage rises but may be garbage-collected.
You can try solving it by caching your node (Label
in a StackPane
in your case) - creating it only once:
final TableCell<Visit, Visit> cell = new TableCell<Visit, Visit>() {
private Label label;
private StackPane pane;
{
// This is the constructor of the anonymous class. Alternatively, you may choose to create the label and pane lazily the first time they're needed.
label = new Label();
pane = new StackPane(label);
pane.setAlignment(Pos.CENTER);
label.setMaxWidth(10);
label.setMinWidth(10);
label.setMinHeight(30);
}
@Override
public void updateItem(Visit item, boolean empty) {
super.updateItem(item, empty);
if (empty || getIndex() < 0) {
setGraphic(null);
setText(null);
return;
}
item = getTableView().getItems().get(getIndex());
setText(item.getStatus().display());
String background = FXMLConstants.toHexString(ColorUtils.getVisitBackgroundColor(item));
pane.setStyle(String.format("-fx-background-color:%s;;", background));
setGraphic(pane);
setText(item.getStatus().display());
setStyle(getStyle() + "-fx-alignment: CENTER_LEFT;");
}
};
Also - what is the use of the label, if you never set its text? What is the contentDisplay
of the cell? Are the nodes even shown?
Upvotes: 3