TableView中的延迟加载项

时间:2018-02-24 12:19:45

标签: javafx tableview

我正在实现一个自定义TableCellFactory来从数据库异步加载数据。查询数据库不应该阻止UI线程。

public abstract class AsynchronousTableCellFactory<E, T> implements Callback<TableColumn<E, T>, TableCell<E, T>> {

private static final Executor exe1 = Executors.newFixedThreadPool(2);

private static final Executor exe2 = Executors.newFixedThreadPool(2);

@Override
public TableCell<E, T> call(final TableColumn<E, T> param) {
    final TableCell<E, T> cell = new TableCell<E, T>() {

        @Override
        public void updateItem(final T item, final boolean empty) {

            super.updateItem(item, empty);

            if (empty) {
                setText(null);
            } else {
                setText("Thinking..");
                // do this later some time, we need to finish here FAST
                exe1.execute(() -> {

                    if (getTableRow() != null) {
                        final Service<T> service = new Service<T>() {

                            @Override
                            protected Task<T> createTask() {
                                return getTask((E) getTableRow().getItem());
                            }
                        };
                        service.setExecutor(exe2);
                        service.setOnSucceeded(e -> {

                            if (e.getSource().getValue() == null) {
                                setText("n/a");
                            } else {
                                setText(e.getSource().getValue().toString());
                            }

                        });
                        service.setOnFailed(e -> {
                            final Throwable t = e.getSource().getException();
                            setText(t.getLocalizedMessage());
                        });
                        service.start();
                    }
                });
            }
        }
    };

    return cell;
}

protected abstract Task<T> getTask(E rowDataItem);

}

它大部分时间都在工作,但并非总是如此。关于它的一个奇怪之处是T item总是null在哪种情况下我可以T item null

相应的表格代码:

public class OriginsTableViewController implements Initializable {

@FXML
private TableView<LazyLoadingOriginWrapper> table;
@FXML
private TableColumn<LazyLoadingOriginWrapper, String> cSampleName;

@Override
public void initialize(final URL location, final ResourceBundle resources) {
    cSampleName.setCellFactory(new AsynchronousOriginTableCellFactory<>(e -> e.getSampleName()));

}

编辑:找到更好的方法here

1 个答案:

答案 0 :(得分:2)

请注意TableCell可以重复使用!这意味着任何项目都可以分配给任何单元格(这就是updateItem方法的用途)。当您的完成处理程序直接设置TableCell的文本时,您当前的代码可能会提出很多问题。

一个简单的解决方案是将结果包装在ObservableValue内的LazyLoadingOriginWrapper内,并在CellValueFactory中使用该结果,而不是创建自己的TableCellObservableValue中的TableView更新将在ObservableValue内可更改(请确保修改'fx-application'主题上的public static class LazyLoadingOriginWrapper { // params are 'bean', 'id/name', 'default value' ObservableStringValue name = new SimpleStringProperty(this, "name", "thinking..."); public ObservableStringValue nameProperty() { return name; } public void setName(String value) { Platform.runLater(() -> name.set(value)); } // add your logic for asynchronious loading here and update the above ObservableValue instead. Make sure you trigger it manually! } @Override public void initialize(final URL location, final ResourceBundle resources) { cSampleName.setCellValueFactory(C -> C.getValue().nameProperty()); } !)。 e.g。

consensus.powLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");