Этот пост является дубликатом моего оригинального блога. Это делается для того, чтобы поддерживать в рабочем состоянии некоторые сообщения из моего старого блога.

Моим первым профессиональным приложением было приложение JavaFX, которое должно было связываться с удаленным сервером и выполнять обычные операции, такие как вход в систему, запросы, загрузка файлов и т. Д. Именно тогда я начал открывать для себя мир потоков и то, насколько он сложен.

В веб-приложениях очень часто большинство асинхронных операций контролируются сервером контейнера приложений (одновременные запросы и т. Д.). То, что происходит в настольных и мобильных приложениях, немного отличается: вы должны управлять всеми своими потоками, включая поток пользовательского интерфейса.

В Android, например, запрещено выполнять операции веб-запросов в основном потоке, потому что задержка сети может привести к зависанию основного потока во время ожидания ответа, и приложение перестает отвечать. Для этого в платформе Android есть класс AsyncTask, который необходимо унаследовать, чтобы облегчить выполнение небольших фоновых задач. У этого класса есть три метода, которые при правильном использовании будут обрабатывать управление потоками для пользователя.

После возникновения аналогичных проблем в моих приложениях JavaFX (вы можете увидеть в Stack Overflow здесь (Остановить потоки перед закрытием моей программы JavaFX), здесь (Остановить потоки перед закрытием моей программы JavaFX) и здесь (ProgressIndicator зависает, когда кнопка нажал. JavaFX) ) Решил реализовать что-то похожее на AsyncTask для JavaFX.

JavaFX AsyncTask



Цель класса - упростить обработку фоновых задач в JavaFX, и он основан на той же идее AsyncTask от Android.

Асинхронная задача определяется вычислением, которое выполняется в фоновом потоке и результат которого публикуется в потоке пользовательского интерфейса. Асинхронная задача определяется расширением класса и реализацией 4 методов, называемых onPreExecute, doInBackground, progressCallback и onPostExecute.

При желании у вас есть метод setDaemon для установки демона потоков, что означает, что если ваше приложение JavaFX было закрыто, оно все еще может работать или нет. setDamon (boolean) может быть вызван только до запуска потока. По умолчанию поток настроен на демон.

Методы

onPreExecute - используется для запуска какой-то процедуры перед запуском фоновой задачи

doInBackground - используется для выполнения фоновых задач

onPostExecute - он используется для запуска некоторой процедуры finally после завершения фоновой задачи

progressCallback - он будет вызываться каждый раз, когда вы вызываете publishProgress для обновления вашего потока пользовательского интерфейса, как вы хотите

publishProgress - он используется для вызова вашего progressCallback и обновления вашего компонента пользовательского интерфейса.

setDaemon - используется для установки демона вашего потока

execute - вызывается для запуска всего процесса

interrupt - он вызывается для прерывания вашего потокового процесса

Пример использования:

public class Example extends AsyncTask {
    private UIController controller;
    public Example(UIController controller) {
        this.controller = controller;
    }
    @Override
    void onPreExecute() {
    
        //This method runs on UI Thread before background task has started
        this.controller.updateProgressLabel("Starting Download")
    }
    @Override
    void doInBackground() {
    //This method runs on background thread
    
    boolean downloading = true;
    
        while (downloading){
        
            /*
            * Your download code
            */
            
            double progress = 65.5 //Your progress calculation 
            publishProgress(progress);
        }
    }
    @Override
    void onPostExecute() {
        //This method runs on UI Thread after background task has done
        this.controller.updateProgressLabel("Download is Done");
    }
    @Override
    void progressCallback(Object... params) {
        //This method update your UI Thread during the execution of background thread
        double progress = (double)params[0]
        this.controller.updateProgress(progress);
    }
}
//To call this class you just need to instatiate and execute: 
Example testing = new Example(myController);
testing.execute();


Gradle

compile group: 'com.victorlaerte', name: 'jfx-asynctask', version: '1.0.1', ext: 'pom'

Maven

<dependency>
    <groupId>com.victorlaerte</groupId>
    <artifactId>jfx-asynctask</artifactId>
    <version>1.0.1</version>
    <type>pom</type>
</dependency>