当前位置: 首页 > 知识库问答 >
问题:

延迟加载FXProperties

和魁
2023-03-14

这是从这里开始的后续行动。

我正在实现一个表,它将数据异步加载到表单元格中。问题是,表单元格有时无法正确更新。有时它会以某种方式“挂起”并永远显示“加载...”。实际值只有在我在表中滚动一点时才会更新。

要复制,请在表格中快速向下滚动应用程序。某些单元格不会显示“延迟加载”值,而是显示占位符字符串。

延迟加载属性如下所示:

public abstract class LazyLoadingStringProperty extends SimpleStringProperty {

public static final String DEFAULT_LOADING_STRING = "Loading..";
private static final ExecutorService exe = Executors.newCachedThreadPool();
private String loadingString = DEFAULT_LOADING_STRING;

private boolean loaded = false;

public LazyLoadingStringProperty() {

}

public boolean isLoaded() {
    return loaded;
}

public void setLoaded(final boolean loaded) {
    this.loaded = loaded;
}

public String getLoadingString() {
    return loadingString;
}

public void setLoadingString(final String loadingString) {
    this.loadingString = loadingString;
}

@Override
public String getValue() {
    if (!loaded) {
        Platform.runLater(() -> startLoadingService());
        return loadingString;
    }
    return super.getValue();
}

protected void startLoadingService() {

    final Service<String> s = new Service<String>() {

        @Override
        protected Task<String> createTask() {
            return LazyLoadingStringProperty.this.createTask();
        }
    };

    s.setExecutor(exe);

    s.setOnFailed(e -> {
        setLoaded(true);
        setValue(s.getException().getLocalizedMessage());

    });

    s.setOnSucceeded(e -> {
        setLoaded(true);
        setValue(s.getValue());

    });
    s.start();
    // System.err.println("Started");
}

protected abstract Task<String> createTask();

}

应用程序如下所示:

public class ExampleTable extends Application {

    private static final int NUM_ELEMENTS = 500;

    private final TableView<ExampleBean> table = new TableView<>();

    private final ObservableList<ExampleBean> data = FXCollections.observableArrayList();

    public static void main(final String[] args) {
        launch(args);
    }

    @Override
    public void start(final Stage stage) {
        final Scene scene = new Scene(new Group());
        stage.setTitle("Table View Sample");
        stage.setWidth(300);
        stage.setHeight(500);

        final TableColumn<ExampleBean, String> c1 = new TableColumn<>("A");
        c1.setCellValueFactory(new PropertyValueFactory<ExampleBean, String>("p1"));
        final TableColumn<ExampleBean, String> c2 = new TableColumn<>("B");
        c2.setCellValueFactory(new PropertyValueFactory<ExampleBean, String>("p2"));
        final TableColumn<ExampleBean, String> c3 = new TableColumn<>("C");
        c3.setCellValueFactory(new PropertyValueFactory<ExampleBean, String>("p3"));

        c1.setPrefWidth(100);
        c2.setPrefWidth(100);
        c3.setPrefWidth(100);


        for (int i = 0; i < NUM_ELEMENTS; i++) {
            data.add(new ExampleBean());
        }

        final ScrollPane sp = new ScrollPane();
        sp.setContent(table);
        sp.setMaxHeight(Double.POSITIVE_INFINITY);
        sp.setMaxWidth(Double.POSITIVE_INFINITY);
        sp.setFitToHeight(true);
        sp.setFitToWidth(true);

        table.setItems(data);
        // table.setMaxHeight(Double.POSITIVE_INFINITY);
        // table.setMaxWidth(Double.POSITIVE_INFINITY);
        table.getColumns().addAll(c1, c2, c3);

        final VBox vbox = new VBox();
        vbox.setSpacing(5);
        VBox.setVgrow(sp, Priority.ALWAYS);
        vbox.getChildren().addAll(sp);

        scene.setRoot(vbox);


        stage.setScene(scene);
        stage.show();
    }
}

完整的可运行代码可以在这里找到。

共有1个答案

甘学潞
2023-03-14

<罢工> 它看起来像JavaFX服务中的一个bug。。。

由于没有保存对服务实例的引用,因此它们被垃圾收集<有时,他们中的一些人在完成任务之前被垃圾收集
在这种情况下,不调用服务的属性的侦听器。

简单的解决方法是使用LazyLoadingStringProperty对象保存服务引用:

...
private ArrayList<Service<String>> services = new ArrayList<>();

protected void startLoadingService() {

    final Service<String> s = new Service<String>() {
        @Override
        protected Task<String> createTask() {
            return LazyLoadingStringProperty.this.createTask();
        }
    };
    services.add(s);
    ...

但是没有必要将一个值与许多任务并行加载。所以每个值一个服务就足够了:

    ...

    private Service<String> s;

    protected void startLoadingService() {

        if (s != null) return; // started already

        s = new Service<String>() {
            ...
 类似资料:
  • 描述 (Description) 延迟加载可应用于图像,背景图像和淡入效果,如下所述 - 对于图像 要在图像上使用延迟加载,请按照给定的步骤进行操作 - 使用data-src属性而不是src属性来指定图像源。 将类lazy添加到图像。 <div class = "page-content"> ... <img data-src = "image_path.jpg" class = "l

  • 问题内容: 我在JPA实体中的延迟加载属性有问题。我读过许多类似的问题,但它们与spring或hibernate有关,并且他们的后代不适用或没有帮助。 该应用程序是在Wildfly应用程序服务器上运行的JEE和JPA2.1。有两个实体,DAO会话bean和servlet将它们放在一起: 当我运行此代码时,它失败并显示: 我对WebLogic / JPA1使用了非常相似的模式,并且运行平稳。任何的想

  • 问题内容: 我想知道在node.js中使用是否等效于延迟加载? 例如,如果我有一个函数需要代码中其他任何地方都不需要的特定node.js包,那么我最好在该函数内部使用它,以便仅在调用该函数时才包含所需的包。 我还不确定是否会由于缺乏对node.js架构的了解而在性能方面有所改善?我想它每次与服务器的连接都会使用更少的内存。但是,当它必须读取程序包时,它会增加磁盘的I / O吗,还是将其添加到内存中

  • 有很多关于“懒惰”的例子和文档。也许我没有明白,但为什么要用它呢?实例化bean成本

  • 问题内容: 如果这是完全相同的内容,请纠正我,我知道这个话题经常被讨论,但是找不到确切的答案。 问题: 在MVC Web应用程序中处理Hibernate对象的最佳实用解决方案是什么? 细节: 我正在使用Hibernate,并希望在可能的情况下利用延迟加载。 我正在使用MVC风格的Webapp。 我讨厌获得延迟加载初始化异常。 我讨厌不得不在事务之间重新连接Hibernate对象。 选项: 渴望装载

  • 问题内容: 假设我们有一个存储客户详细信息的系统和一个存储员工详细信息的系统(假设情况!)。当EmployeeSystem访问Employee时,使用IUserType中实现的WCF从ClientSystem访问Client信息: NHibernate映射: IUserType的实现: 即使我在属性上具有lazy =“ true”,它也会在加载Employee时立即加载Client。这是正确的行为