Platform.runLater y Tarea en JavaFX

He estado investigando sobre esto pero todavía estoy MUY confundido por decir lo menos.

¿Alguien puede darme un ejemplo concreto de cuándo usar Task y cuándo usar Platform.runLater(Runnable); ? ¿Cuál es exactamente la diferencia? ¿Hay una regla de oro para cuándo usar cualquiera de estos?

También corrígeme si me equivoco, pero ¿no son estos dos “Objetos” una forma de crear otro hilo dentro del hilo principal en una GUI (usada para actualizar la GUI)?

Utilice Platform.runLater(...) para operaciones rápidas y sencillas y Task para operaciones complejas y grandes.

  • Caso de uso para Platform.runLater(...)
  • Caso de uso para la Task : Ejemplo de tarea en la aplicación Ensemble

Ejemplo: ¿Por qué no podemos usar Platform.runLater(...) para cálculos largos (Tomado de la referencia a continuación).

Problema: hilo de fondo que solo cuenta de 0 a 1 millón y barra de progreso de actualización en la interfaz de usuario.

Código usando 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(); 

Este es un horrible trozo de código, un crimen contra la naturaleza (y la progtwigción en general). Primero, perderás células cerebrales solo mirando esta doble anidación de Runnables. En segundo lugar, va a inundar la cola de eventos con poco Runnables, un millón de ellos, de hecho. Claramente, necesitábamos algo de API para que sea más fácil escribir trabajadores en segundo plano que luego se comunican con la interfaz de usuario.

Código usando Tarea:

 Task task = new Task() { @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(); 

no sufre ninguno de los defectos exhibidos en el código anterior

Referencia: Trabajador de enhebrado en JavaFX 2.0

  • Platform.runLater : si necesita actualizar un componente de GUI a partir de un hilo que no sea GUI, puede usarlo para poner su actualización en una cola y será manejada por el hilo de la GUI lo antes posible.
  • Task implementa la interfaz Worker que se usa cuando necesita ejecutar una tarea larga fuera del hilo de la GUI (para evitar congelar su aplicación) pero aún necesita interactuar con la GUI en algún momento.

Si está familiarizado con Swing, el primero es equivalente a SwingUtilities.invokeLater y el último al concepto de SwingWorker .

El javadoc de Task da muchos ejemplos que deberían aclarar cómo se pueden usar. También puede consultar el tutorial sobre concurrencia .

Ahora se puede cambiar a la versión 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); } }); } 

Una de las razones para usar una Plataforma explicita. RunLater () podría ser que vinculó una propiedad en la interfaz de usuario a una propiedad de servicio (resultado). Entonces, si actualiza la propiedad del servicio enlazado, debe hacer esto a través de runLater ():

En el hilo de UI también conocido como el hilo de la aplicación JavaFX:

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

en la implementación del servicio (trabajador de fondo):

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