JavaFX中处理比较耗时的任务或操作,在不阻塞UI线程的情况下需要用到 javafx.concurrent.Task类;Task
实现了 Worker
和 EventTarget
接口,并且继承了 java.util.concurrent.FutureTask
类,可视为Java线程与JavaFX事件机制之间的桥梁。 Task
可作为普通R unnable
直接供 Thread
使用,也可作为 Callable
传递给 ExecutorService
。无论是哪种情况,均可先用业务委托封装无法异步执行的同步。Task
由 Runnable
和 F uture
组成,因此可由 Thread
直接执行, 以下是调用示例:
Task<Integer> task = new Task<Integer>() {
@Override
protected Integer call() throws Exception {
int iterations;
for (iterations = 0; iterations < 100000; iterations++) {
if (isCancelled()) {
break;
}
}
return iterations;
}
@Override
protected void running() {
updateMessage("running...");
}
@Override
protected void succeeded() {
updateMessage("Done!");
int value = getValue();
System.out.println(value);
}
@Override
protected void cancelled() {
updateMessage("Cancelled!");
}
@Override
protected void failed() {
updateMessage("Failed!");
}
};
new Thread(task).start();
//根据实际需要处理消息值
task.messageProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
System.out.println(newValue);
}
});
经测试我们知道call()方法是在新开启的线程中运行,我们可以在此方法中执行自己的任务,例如从网络获取数据或上传数据到服务器上;该方法可根据实际情况返回自己需要的数值,有点类似于Android中的AsyncTask类的doBackgroud(...)方法,在些方法中不可以直接处理应用中UI控件,不在同一线程中访问JavaFX Application线程中的成员是不安全的,我们可以在successeded()这个方法中处理任务运行后的结果,successeded()方法运行在JavaFx Application线程中,我们可以查看原码验证。
public final void setOnSucceeded(EventHandler<WorkerStateEvent> value) {
checkThread();
getEventHelper().setOnSucceeded(value);
}
private void checkThread() {
if (started && !isFxApplicationThread()) {
throw new IllegalStateException("Task must only be used from the FX Application Thread");
}
}