我正在编写一个可以更新自己的程序。我创建了一个单独的线程来检查服务器的更新(因为不阻止UI更新)。一旦更新完成检查,并确定有更新版本可用,它应该询问用户是否希望获得这些更新。
这是我的shouldApplyUpdates
方法:
public boolean shouldApplyUpdate() {
Alert updateAlert = new Alert(Alert.AlertType.CONFIRMATION);
updateAlert.setTitle(resourceBundle.getString("ui.gui.update.title"));
updateAlert.setContentText(resourceBundle.getString("ui.gui.update.message"));
Optional<ButtonType> ret = updateAlert.showAndWait();
return ret.get() == ButtonType.OK;
}
它应该做的是提示用户是否要应用更新,如果是,则返回true。问题是,因为这个方法是从另一个线程调用的,所以抛出异常就不会出现在JavaFX应用程序线程上(在我的情况下,无声地,所以我不得不用try / catch包围方法来查看异常)。
这是我的更新主题:
new Thread(new Task<Void>() {
@Override
protected Void call() throws Exception {
//Check for updates
...
//If updates are available, call shouldApplyUpdates()
if(shouldApplyUpdates()){
//Apply the updates
}
return null;
}
}).start();
//Create GUI and stuffs, all should be happening while updates are being checked
所以我需要的是创建并在Application Thread上显示对话框,然后阻止该方法返回(由于单独的线程,该方法是安全的被阻止)。然后在用户确认他的选择后,返回方法。
实现这一目标的最佳方法是什么?
答案 0 :(得分:1)
我不确定您是否需要阻止该方法返回。你可以这样做:
Task<Boolean> checkForUpdateTask = new Task<Boolean>() {
@Override
public Boolean call() throws Exception {
// check for updates...
if (/* updates available */) {
return true ;
} else {
return false ;
}
}
};
checkForUpdateTask.setOnSucceeded(e -> {
if (checkForUpdateTask.getValue() && shouldApplyUpdates()) {
// apply updates...
} else {
// proceed....
}
});
checkForUpdateTask.setOnFailed(e -> {
checkForUpdateTask.getException().printStackTrace();
});
new Thread(checkForUpdateTask).start();
如果确实需要阻止该方法返回,可以使用以下习语。这是基于JavaFX2: Can I pause a background Task / Service?
的解决方案Task<Void> checkForUpdateTask = new Task<Void>() {
@Override
public Void call() throws Exception {
// check for updates...
if (/* updates available */) {
FutureTask<Boolean> checkUser = new FutureTask<Boolean>(() -> shouldApplyUpdates());
Platform.runLater(checkUser);
// checkUser.get() will block until it returns a value...
if (checkUser.get()) {
// apply updates...
}
}
return null ;
}
};
new Thread(checkForUpdateTask).start();
在这个版本中,// apply updates...
代码块在后台线程上执行,这可能就是你想要的。