-
Bug
-
Resolution: Unresolved
-
P3
-
jfx20, jfx17, jfx22, jfx23, jfx24
A DESCRIPTION OF THE PROBLEM :
The recalculateAndImproveEstimatedSize() method of VirtualFlow is called when a control is resized. This method will request DEFAULT_IMPROVEMENT new items from the backing list each time it is called, even if the visible rows do not change (e.g. horizontal resizing). Resizing a window can trigger repeated calls to recalculate and may quickly cause all elements in the backing list to be retrieved. This behavior is problematic if the backing list is lazily loaded, as it can effectively negate any lazy retrieval or instantiation.
It appears that this behavior is a side effect of the solution toJDK-8089589. I suspect that this could be resolved by looking ahead a fixed amount beyond visible rows, rather than looking ahead an additional DEFAULT_IMPROVEMENT items on each recalculation.
https://bugs.openjdk.org/browse/JDK-8089589
REGRESSION : Last worked in version 16
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a list implementation that will log calls to get() console
2. Add lots of items to an instance of the list (e.g. 1000 strings).
3. Create a ListView backed by the list.
4. Launch application and resize the window horizontally, increasing and decreasing the window width while watching the console output to see the pattern of list item retrievals. Eventually VirtualFlow will have triggered a request of each item in the list.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Only minimal number of items necessary to display and provide for stable scrolling should be retrieved (see https://bugs.openjdk.org/browse/JDK-8089589).
ACTUAL -
Additional list items are retrieved on each recalculate until all list items are eventually retrieved.
---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.ModifiableObservableListBase;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class HelloFX extends Application {
public static final class PrintOnGetList<E> extends ModifiableObservableListBase<E> {
private final List<E> delegate = new ArrayList<>();
public E get(int index) {
System.err.println("get(" + index + ")");
return delegate.get(index);
}
public int size() {
return delegate.size();
}
protected void doAdd(int index, E element) {
delegate.add(index, element);
}
protected E doSet(int index, E element) {
return delegate.set(index, element);
}
protected E doRemove(int index) {
return delegate.remove(index);
}
}
private final PrintOnGetList<String> list = new PrintOnGetList<>();
@Override
public void start(Stage stage) {
for(int i=0; i<=999; i++) {
list.add("Item " + i);
}
ListView<String> listView = new ListView<>(list);
BorderPane borderPane = new BorderPane();
Label label = new Label("Resize horizontally to see get() calls to the list");
borderPane.setTop(label);
borderPane.setCenter(listView);
Scene scene = new Scene(borderPane, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
---------- END SOURCE ----------
FREQUENCY : always
The recalculateAndImproveEstimatedSize() method of VirtualFlow is called when a control is resized. This method will request DEFAULT_IMPROVEMENT new items from the backing list each time it is called, even if the visible rows do not change (e.g. horizontal resizing). Resizing a window can trigger repeated calls to recalculate and may quickly cause all elements in the backing list to be retrieved. This behavior is problematic if the backing list is lazily loaded, as it can effectively negate any lazy retrieval or instantiation.
It appears that this behavior is a side effect of the solution to
https://bugs.openjdk.org/browse/JDK-8089589
REGRESSION : Last worked in version 16
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a list implementation that will log calls to get() console
2. Add lots of items to an instance of the list (e.g. 1000 strings).
3. Create a ListView backed by the list.
4. Launch application and resize the window horizontally, increasing and decreasing the window width while watching the console output to see the pattern of list item retrievals. Eventually VirtualFlow will have triggered a request of each item in the list.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Only minimal number of items necessary to display and provide for stable scrolling should be retrieved (see https://bugs.openjdk.org/browse/JDK-8089589).
ACTUAL -
Additional list items are retrieved on each recalculate until all list items are eventually retrieved.
---------- BEGIN SOURCE ----------
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.collections.ModifiableObservableListBase;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class HelloFX extends Application {
public static final class PrintOnGetList<E> extends ModifiableObservableListBase<E> {
private final List<E> delegate = new ArrayList<>();
public E get(int index) {
System.err.println("get(" + index + ")");
return delegate.get(index);
}
public int size() {
return delegate.size();
}
protected void doAdd(int index, E element) {
delegate.add(index, element);
}
protected E doSet(int index, E element) {
return delegate.set(index, element);
}
protected E doRemove(int index) {
return delegate.remove(index);
}
}
private final PrintOnGetList<String> list = new PrintOnGetList<>();
@Override
public void start(Stage stage) {
for(int i=0; i<=999; i++) {
list.add("Item " + i);
}
ListView<String> listView = new ListView<>(list);
BorderPane borderPane = new BorderPane();
Label label = new Label("Resize horizontally to see get() calls to the list");
borderPane.setTop(label);
borderPane.setCenter(listView);
Scene scene = new Scene(borderPane, 640, 480);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
---------- END SOURCE ----------
FREQUENCY : always
- relates to
-
JDK-8089589 [ListView] ScrollBar content moves toward-backward during scrolling.
- Resolved