如何在javafx中操纵Future的结果

时间:2015-03-08 17:25:38

标签: java model-view-controller javafx javafx-8 future

这是我的JavaFX控制器

public class MainController {
   private Future<Graph> operation;
   private ExecutorService executor = Executors.newSingleThreadExecutor();

   @FXML
   private void createSession() { //invoked by a button click in the view
      //GraphCreationSession implements Callable<Graph>
      GraphCreationSession graphSession = new GraphCreationSession();

      if (operation != null && !operation.isDone()) {
         //cancel previous session
         operation.cancel(true);
      }
      operation = executor.submit(graphSession);
      ???
    }
 }

所以我的问题是,在javaFX上下文中处理Future的结果的成语是什么?

我知道我可以做operation.get()并且线程将阻塞直到操作完成,但我将阻止Application线程。我在Callable完成后发现了一个回调,我发现了CompletableFuture,这种做法是通过 thenAccept 进行的,但基于{{{ 3}}线程仍然会被阻止,这会破坏未来的点,就像答案所提到的那样。

在我的特定情况下,Callable的结果(我的示例中的图形)包含我希望在操作完成时在面板中显示的结果。

1 个答案:

答案 0 :(得分:3)

最简单的方法是更改​​GraphCreationSession,使其成为Task<Graph>的子类,而不是Callable<Graph>的实现:

public class GraphCreationSession extends Task<Graph> {

    @Override
    public Graph call() throws Exception {
        // implementation as before...
    }
}

然后你可以做

public class MainController {
   private ExecutorService executor = Executors.newSingleThreadExecutor();
   private GraphCreationSession graphSession ;

   @FXML
   private void createSession() { //invoked by a button click in the view

      if (graphSession != null && !graphSession.getState()==Worker.State.RUNNING) {
         //cancel previous session
         graphSession.cancel(true);
      }
      graphSession = new GraphCreationSession();
      graphSession.setOnSucceeded(event -> {
          Graph graph = graphSession.getValue();
          // update UI...
      });
      executor.execute(graphSession);
    }
 }

如果您无法更改GraphCreationSession,或者希望它独立于javafx API,那么只需将其包装在一个简单的Task实现中:

public class MainController {

    private Task<Graph> graphSession ;
    // ...

    @FXML
    public void createSession() {

        // ...

        graphSession = new Task<Graph>() {
            @Override
            public Graph call() throws Exception {
                return new GraphCreationSession().call();
            }
        };

        graphSession.setOnSucceeded(...);
        executor.execute(graphSession);
   }
}