在javafx

时间:2018-01-02 05:59:19

标签: javafx concurrency task

我有一个函数,它应该从Task API的结果中返回一个列表。

    @Override
    public List performQuery(boolean isPaginationQuery, boolean isSortingQuery {

        try {
            TaskImpl taskImpl = new TaskImpl(isPaginationQuery,
                    isSortingQuery);
            queryExecutor.submit(taskImpl).get();
            return taskImpl.get();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

执行更新的内部类

private class TaskImpl extends Task<List> {

        private boolean isPaginationQuery, isSortingQuery;

        public TaskImpl(boolean isPaginationQuery, boolean isSortingQuery) {
            this.isPaginationQuery = isPaginationQuery;
            this.isSortingQuery = isSortingQuery;
        }

        @Override
        protected List call() throws Exception {
             Platform.runLater(() -> {
                  loaderContainer.setVisible(true);
                  loaderContainer.toFront();
             });

            HSession hSession = new HSession();
            TaskInfoDao taskInfoDao = new TaskInfoDaoImpl(hSession.getSession(), currentConnection.getConnectionId());
            if (!isPaginationQuery && !isSortingQuery) {
                paginator.setTotal(taskInfoDao.getTaskInfoWithFiltersCount(paginator.getFilterMap(), false));
            }
            Stream<TaskInfo> resultStream = taskInfoDao.getTaskInfoWithFilters(paginator.getFilterMap(), false,
                    paginator.getStartIndex() * paginator.getPageSize(),
                    paginator.getPageSize() * paginator.getPageGap());
            List<TaskInfoTableView> data = createData(resultStream);
            hSession.close();
            return data;
        }

        @Override
        protected void succeeded() {
            super.succeeded();

            try {
                //set the pagination if the task is complete
                //and it is not a pagination query
                if (!isPaginationQuery) {
                    ((TaskInfoViewController) uiController).setPagination(
                            FXCollections.observableArrayList(get()));
                }
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void cancelled() {
            super.cancelled();
            updateMessage("Cancelled!");
        }

        @Override
        protected void failed() {
            super.failed();
            updateMessage("Failed!");
        }
    }

performQuery函数调用线程并等待其结果。

使用Platform.runLater从TaskImpl类内部显示加载器 但是,在任务完成之后才会出现加载程序,即在完成call()函数执行后出现加载程序。

当我删除taskImpl.get()时,加载器工作正常
任何帮助表示赞赏。

P.S。 :无论如何,我需要在Inner类之外的Task API的结果(在TaskImpl之外)

1 个答案:

答案 0 :(得分:2)

首先,您似乎对异步编程不是很熟悉。让performQuery()返回List表示您希望同步运行此 - 在获得结果之前,您无法返回结果。这正是你冻结UI的原因。

了解异步编程的重要一点是,您将启动在另一个线程中执行某些操作(即任务),并立即返回 。当从任务返回结果时,您切换回UI(JavaFX Application)线程以更新它。您可以将此视为事件驱动方法。

因此,对于您的情况,您应该在performQuery()类中已覆盖的succeeded()方法中直接更新列表(您在TaskImpl中返回的列表)。< / p>

如果您要更新的列表不在TaskImpl的范围内,那么您可以使用java.util.function包中的功能接口为您执行此操作。这意味着您将在正确的范围内创建该功能接口对象,并在对象构造期间传入TaskImpl,并在succeeded()中调用该接口。

更新

如果我认为这就是调用performQuery()

public class MyController {
    @FXML
    TableView<Foo> tableView;

    public void initialize() {
        List result = queryController.performQuery(true, true);
        tableView.getItems().addAll(result);
    }
}

然后,我可能会做这样的事情:

public class MyController {
    @FXML
    TableView<Foo> tableView;

    public void initialize() {
        List result = queryController.performQuery(true, true, list -> tableView.getItems.addAll(list));
    }
}

public class QueryController {
    @Override
    public void performQuery(boolean isPaginationQuery, boolean isSortingQuery, java.util.function.Consumer<List> onQuerySucceeded) {

        try {
            TaskImpl taskImpl = new TaskImpl(isPaginationQuery,
                    isSortingQuery, onQuerySucceeded);

            queryExecutor.submit(taskImpl);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

private class TaskImpl extends Task<List> {

    private final java.util.function.Consumer<List> onQuerySucceeded;

    public TaskImpl(boolean isPaginationQuery, boolean isSortingQuery, java.util.function.Consumer<List> onQuerySucceeded) {
        this.isPaginationQuery = isPaginationQuery;
        this.isSortingQuery = isSortingQuery;

        this.onQuerySucceeded = onQuerySucceeded;
    }

    @Override
    protected void succeeded() {
        super.succeeded();

        // Not sure what the original codes are doing.
        try {
            //set the pagination if the task is complete
            //and it is not a pagination query
            if (!isPaginationQuery) {
                ((TaskInfoViewController) uiController).setPagination(
                        FXCollections.observableArrayList(get()));
            }
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        // This is what is being added in
        onQuerySucceeded.accept(this.getValue());
    }
}