Запустите службу в фоновом потоке
Могу ли я запустить службу в фоновом потоке?
Я хочу загрузить данные из базы данных, и во время загрузки данных я хочу, чтобы индикатор выполнения отображал прогресс. Сначала я создал задачу, запустил ее в фоновом потоке, а затем обновил индикатор выполнения в соответствии с этой задачей. Тем не менее, я обнаружил, что это задание нельзя использовать повторно, поэтому в следующий раз, когда я нажал кнопку, это не сработало. Позже я обнаружил, что Сервис может запускать Задачи несколько раз, поэтому я инкапсулировал эти задачи внутри Сервиса.
Теперь он отлично работает - каждый раз, когда я нажимаю кнопку, таблица перезагружается - за исключением того, что индикатор выполнения не движется.
Как я могу достичь желаемого результата?
1 ответ
Хорошо... Вот готовый код: https://mega.nz/#!yUsjgJyZ!DHfuBqsujAHurS-pQ_W5y8BAflOtvxsm48goRPkDsxA
Во-первых, я хочу сказать вам, какова моя цель:
Когда я запускаю программу, я хочу, чтобы индикатор выполнения находился в неопределенном состоянии. После нажатия на кнопку, я хочу, чтобы индикатор выполнения отражал прогресс службы. После завершения службы, я хочу, чтобы индикатор выполнения был завершен (100%).
Вот что я нашел. Похоже, сервис автоматически запускает свою задачу в фоновом потоке. Я построил программу "песочницы", где я играл со службами и индикатором выполнения. Программа состояла из индикатора выполнения, двух текстовых полей с двумя кнопками над ними. Первая кнопка может запустить service_countTo100, а вторая кнопка может запустить service_getActualCount.
Теперь в файле fxml я установил индикатор выполнения в неопределенное состояние по умолчанию. После нажатия кнопки 1 начался отсчет (отображается в text_field1), и индикатор выполнения изменился в соответствии с фактическим прогрессом. После нажатия кнопки 2 фактическое значение счетчика отображается в поле text_field2. И тут возникают некоторые проблемы. Чтобы продемонстрировать проблемы, я покажу вам исходный код службы:
// Create the service
public static Service<Integer> serviceTo100 = new Service<Integer>() {
@Override
protected Task<Integer> createTask() {
Task<Integer> taskTo100 = new Task<Integer>() {
@Override protected Integer call() throws Exception {
int iterations;
updateProgress(-1, 100);
for (iterations = 0; iterations < 100; iterations++) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
updateMessage("Iteration " + iterations);
updateProgress(iterations, 100);
// Now block the thread for a short time, but be sure
// to check the interrupted exception for cancellation!
try {
Thread.sleep(100);
} catch (InterruptedException interrupted) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
}
}
//udpateProgress(100, 100);
return iterations;
}
};
return taskTo100;
}
};
Как видите, есть простой цикл, который насчитывает от 0 до 100, а также есть updateProgress(iterations, 100);
заявление, которое обновляет прогресс. Этот сервис находится в Services
учебный класс. В FXMLDocumentController.java вызывается метод runService(Service service)
определяется как это:
public void runService(Service service){
service.start();
progressBar.progressProperty().bind(service.progressProperty());
service.setOnSucceeded((event) -> {
service.reset();
progressBar.progressProperty().unbind();
progressBar.setProgress(1);
});
}
initialize
выглядит так:
@Override
public void initialize(URL url, ResourceBundle rb) {
btn_start1.setOnAction((event) -> {
Service service = Services.serviceTo100;
runService(service);
txt_field1.textProperty().bind(service.messageProperty());
System.out.printf("something\n");
});
.
.
.
}//end of initialize
Теперь самое интересное (по крайней мере для меня, новичка) вступает в игру.
В определении сервиса вы можете заметить закомментированную строку //updateProgress(100,100)
, Это была моя попытка установить индикатор выполнения в завершенное состояние, когда подсчет остановился. Но ява проигнорировала эту строчку. Я пытался поставить System.out.print("Something");
и это сработало, но updateProgress(100, 100)
не сделал. Когда подсчет завершился, индикатор выполнения был установлен в состояние по умолчанию, определенное в файле fxml, которое было неопределенным.
Вывод: класс Service создает задание, определенное внутри него, и после того, как задание выполнено, задача больше не существует, поэтому нет прогресса, связанного с индикатором выполнения.
Даже если задача больше не существует, вы не можете установить прогресс ограниченного индикатора выполнения с помощью setProgress(double double)
метод. Сначала нужно отсоединить его.
Теперь я получил то, что мне было нужно:
Вы запускаете программу, индикатор выполнения находится в неопределенном состоянии, ожидая попадания. Вы нажимаете кнопку, сервис начинает считать до 100, а индикатор выполнения прогрессирует в соответствии с ProProperty службы. Когда подсчет завершен, индикатор выполнения снова устанавливается в неопределенное состояние, ожидая другого запуска.