启动任务时无响应的UI

时间:2013-06-06 12:59:13

标签: java multithreading concurrency javafx-2

我有一个Task应该从数据库中返回SomeObject列表:

public final class LoadTask extends Task<List<SomeObject>> {       

    @Override
    protected List<TodoTask> call() throws InterruptedException {
        List<SomeObject> list = FXCollections.observableArrayList();
            list.addAll(servcie.getAllSomeObjects());
            // this task take a lot of time
        return list;
    }           
}

我使用此任务填充TableView

@FXML
private void pullData() throws InterruptedException, ExecutionException {
    loadTask1 = new LoadTask();
    final Thread t = new Thread(loadTask1);
    t.start();
    todoList.getItems().addAll(loadTask1.get());
}

当我按下执行pullData()整个UI冻结的按钮,直到我从数据库中获取所有对象。

如何修复设计以获得响应式UI

2 个答案:

答案 0 :(得分:0)

以下是我如何实现它。基本上,我开始一项新任务,并将监听器放在该任务上以便成功完成。 costingService是一个接口hibernate连接(通过glassfish)到MS SqlServer DB。该接口上的listProducts方法返回数据库中的所有产品。 loadTask包含任务完成时数据库查询的结果。 pricingProductTableList是查询结果的ObservableList,而pricingProductTable是显示数据的TableView。这是代码:

    private ObservableList<Product> getProductList() {
    logger.info("Entering {}.getProductList", this.getClass().getName());
    if (costingService == null) {
        return null;
    }
    final Task<ObservableList> loadTask = new Task<ObservableList>() {
        @Override
        protected ObservableList call() throws Exception {
            return FXCollections.observableList(costingService.listProducts());
        }
    };

    loadTask.stateProperty().addListener(new ChangeListener<Worker.State>() {
        @Override
        public void changed(ObservableValue<? extends Worker.State> source, Worker.State oldState, Worker.State newState) {
            if (newState.equals(Worker.State.SUCCEEDED)) {
                if (pricingProductTableList != null && !pricingProductTableList.isEmpty()) {  // moved here from beginning of method, now table doesn't redraw
                    pricingProductTableList.clear();
                }
                pricingProductTableList = loadTask.getValue();
                pricingProductTable.getItems().setAll(pricingProductTableList);
                pricingProductTable.getColumns().get(0).setVisible(false);
                pricingProductTable.getColumns().get(0).setVisible(true);
                }
            } else if (newState.equals(Worker.State.FAILED)) {
                loadTask.getException().printStackTrace();
            }
        }
    });

    new Thread(loadTask).start();

    return pricingProductTableList;
}

答案 1 :(得分:0)

您可以将ListView定义为String的ListView,将您的任务定义为String的ObservableList的任务。之后,您可以将listview的items属性绑定到任务值属性,如下所示:

listview.itemsProperty().bind(task.valueProperty());

这是一个更大的例子:

public void start(Stage stage) throws Exception {
    VBox vbox = new VBox(10.0);
    vbox.setAlignment(Pos.CENTER);

    final ListView<String> listview = new ListView<String>();

    final ProgressBar bar = new ProgressBar(-1);
    bar.setVisible(false);

    final Button button = new Button("Fill");
    button.setOnAction(new EventHandler<ActionEvent>() {            
        @Override
        public void handle(ActionEvent event) {
            final Task<ObservableList<String>> task = new Task<ObservableList<String>>() {
                @Override
                protected ObservableList<String> call() throws Exception {
                    ObservableList<String> items = FXCollections.observableArrayList();
                    for (int i = 0; i < 50000; i++) {
                        items.add("Row#"+i);
                    }
                    return items;
                }                   
            };              
            bar.visibleProperty().bind(task.runningProperty());
            button.disableProperty().bind(task.runningProperty());
            listview.itemsProperty().bind(task.valueProperty());                
            Thread t = new Thread(task);
            t.start();
        }
    });     

    vbox.getChildren().addAll(listview, button, bar);
    Scene scene = new Scene(vbox, 300, 300);
    stage.setScene(scene);
    stage.show();
}

希望它有所帮助。