web-dev-qa-db-fra.com

Platform.runLater et Task dans JavaFX

J'ai fait des recherches à ce sujet mais je suis encore TRÈS confus pour le moins.

Quelqu'un peut-il me donner un exemple concret de quand utiliser Task et quand utiliser Platform.runLater(Runnable);? Quelle est exactement la différence? Existe-t-il une règle d'or pour utiliser l'un ou l'autre?

Corrigez-moi également si je me trompe, mais ces deux "objets" ne sont-ils pas un moyen de créer un autre thread dans le thread principal d'une interface graphique (utilisé pour la mise à jour de l'interface graphique)?

75
Marc Rasmussen

Utilisez Platform.runLater(...) pour des opérations simples et rapides et Task pour des opérations complexes et volumineuses.

Exemple: Pourquoi ne pouvons-nous pas utiliser Platform.runLater(...) pour des calculs longs (Tiré de la référence ci-dessous).

Problème: le fil d’arrière-plan ne compte que de 0 à 1 million et met à jour la barre de progression dans l’UI.

Code utilisant 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();

C'est un morceau de code hideux, un crime contre nature (et la programmation en général). Tout d’abord, vous allez perdre les cellules cérébrales en regardant simplement cette double imbrication de Runnables. Deuxièmement, il va submerger la file d’événements avec de petits Runnables - un million d’entre eux en fait. De toute évidence, nous avions besoin d’API pour faciliter l’écriture de travailleurs d’arrière-plan qui communiquent avec l’UI.

Code à l'aide de Task:

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();

il ne souffre d'aucun des défauts exposés dans le code précédent

Référence: Threading des travailleurs dans JavaFX 2.

91
invariant
  • Platform.runLater: Si vous devez mettre à jour un composant d'interface graphique à partir d'un thread non graphique, vous pouvez l'utiliser pour placer votre mise à jour dans une file d'attente. Elle sera traitée par le thread d'interface graphique dès que possible.
  • Task implémente l'interface Worker qui est utilisée lorsque vous devez exécuter une tâche longue en dehors du thread d'interface graphique (pour éviter de geler votre application), mais que vous devez néanmoins interagir avec l'interface graphique à un moment donné.

Si vous connaissez Swing, le premier est équivalent à SwingUtilities.invokeLater et le dernier au concept de SwingWorker.

Le javadoc de Task donne de nombreux exemples qui devraient préciser comment ils peuvent être utilisés. Vous pouvez également vous référer à le didacticiel sur la simultanéité .

53
assylias

Il peut maintenant être changé en version lambda

@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);
        }
    });
}
9
Caglar Sekmen

Une raison d'utiliser explicitement Platform.runLater () pourrait être que vous avez lié une propriété de l'interface utilisateur à une propriété de service (résultat). Donc, si vous mettez à jour la propriété du service lié, vous devez le faire via runLater ():

Dans le thread d'interface utilisateur également appelé thread d'application JavaFX:

...    
listView.itemsProperty().bind(myListService.resultProperty());
...

mise en œuvre en service (agent d'arrière-plan):

...
Platform.runLater(() -> result.add("Element " + finalI));
...
2
Alexander Pietsch