Платформа.runLater и задача в JavaFX
я проводил некоторые исследования по этому поводу, но я все еще очень смущен, чтобы сказать меньше.
может ли кто-нибудь дать мне конкретный пример того, когда использовать Task
и когда использовать Platform.runLater(Runnable);
? Какая разница? Есть ли золотое правило, когда использовать любой из них?
также исправьте меня, если я ошибаюсь, но не являются ли эти два "объекта" способом создания другого потока внутри основного потока в GUI (используется для обновления GUI)?
4 ответов
использовать Platform.runLater(...)
для быстрых и простых операций и Task
для сложных и больших операций .
пример: почему мы не можем использовать Platform.runLater(...)
для длинных вычислений (взятых из Ниже ссылки).
проблема: фоновый поток, который просто считает от 0 до 1 миллиона и обновляет индикатор выполнения в ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС.
код с помощью Platform.runLater(...)
:
final ProgressBar bar = new ProgressBar();
new Thread(new Runnable() {
@Override public void run() {
for (int i = 1; i <= 1000000; i++) {
final int counter = i;
Platform.runLater(new Runnable() {
@Override public void run() {
bar.setProgress(counter / 1000000.0);
}
});
}
}).start();
это отвратительный кусок кодекса, преступление против природы (и программирование в целом). Во-первых, вы потеряете клетки мозга, просто глядя в этой двойной вложенности Runnables. Во-вторых, он собирается заболотить очередь событий с маленькими Runnables-миллион из них на самом деле. Ясно, что нам нужен какой-то API, чтобы упростить написание фона работники которые после этого связывают назад с пользовательский интерфейс.
код с помощью задачи:
Task task = new Task<Void>() {
@Override public Void call() {
static final int max = 1000000;
for (int i = 1; i <= max; i++) {
updateProgress(i, max);
}
return null;
}
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
он не страдает ни от одного из недостатков, показанных в предыдущем коде
ссылки : рабочий поток в JavaFX 2.0
-
Platform.runLater
: Если вам нужно обновить компонент GUI из потока без GUI, вы можете использовать это, чтобы поместить свое обновление в очередь, и оно будет обработано потоком GUI как можно скорее. -
Task
осуществляетWorker
интерфейс, который используется, когда вам нужно запустить длинную задачу вне потока GUI (чтобы избежать замораживания вашего приложения), но все равно нужно взаимодействовать с GUI на каком-то этапе.
если вы знакомы с Swing, то бывшее эквивалентно SwingUtilities.invokeLater
и последнее к понятию SwingWorker
.
на javadoc задачи дает много примеров, которые должны прояснить, как их можно использовать. Вы также можете обратиться к учебник по параллелизмом.
теперь его можно изменить на лямбда-версию
@Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(() -> {
try {
//an event with a button maybe
System.out.println("button is clicked");
} catch (IOException | COSVisitorException ex) {
Exceptions.printStackTrace(ex);
}
});
}
одна причина использовать платформу explicite.runLater () может быть, вы привязали свойство в пользовательском интерфейсе к свойству service (result). Поэтому, если вы обновите свойство связанного сервиса, вы должны сделать это через runLater ():
в потоке пользовательского интерфейса, также известном как поток приложения JavaFX:
...
listView.itemsProperty().bind(myListService.resultProperty());
...
в реализации службы (фоновый работник):
...
Platform.runLater(() -> result.add("Element " + finalI));
...