60 * A fully observable implementation of a {@link FutureTask}. {@code Task} exposes
61 * additional state and observable properties useful for programming asynchronous
62 * tasks in JavaFX, as defined in the {@link Worker} interface. An implementation
63 * of Task must override the {@link javafx.concurrent.Task#call()} method. This method
64 * is invoked on the background thread. Any state which is used in this method
65 * must be safe to read and write from a background thread. For example, manipulating
66 * a live scene graph from this method is unsafe and will result in runtime
67 * exceptions.
68 * </p>
69 * <p>
70 * Tasks are flexible and extremely useful for the encapsulation of "work". Because
71 * {@link Service} is designed to execute a Task, any Tasks defined by the application
72 * or library code can easily be used with a Service. Likewise, since Task extends
73 * from FutureTask, it is very easy and natural to use a Task with the java concurrency
74 * {@link java.util.concurrent.Executor} API. Since a Task is Runnable, you
75 * can also call it directly (by invoking the {@link javafx.concurrent.Task#run()} method)
76 * from another background thread. This allows for composition of work, or pass it to
77 * a new Thread constructed and executed manually. Finally, since you can
78 * manually create a new Thread, passing it a Runnable, it is possible to use
79 * the following idiom:
80 * <pre><code>
81 * Thread th = new Thread(task);
82 * th.setDaemon(true);
83 * th.start();
84 * </code></pre>
85 * Note that this code sets the daemon flag of the Thread to true. If you
86 * want a background thread to prevent the VM from existing after the last
87 * stage is closed, then you would want daemon to be false. However, if
88 * you want the background threads to simply terminate after all the
89 * stages are closed, then you must set daemon to true.
90 * </p>
91 * <p>
92 * Although {@link java.util.concurrent.ExecutorService} defines several methods which
93 * take a Runnable, you should generally limit yourself to using the <code>execute</code>
94 * method inherited from {@link java.util.concurrent.Executor}.
95 * </p>
96 * <p>
97 * As with FutureTask, a Task is a one-shot class and cannot be reused. See {@link Service}
98 * for a reusable {@link Worker}.
99 * </p>
100 * <p>
101 * Because the Task is designed for use with JavaFX GUI applications, it ensures
102 * that every change to its public properties, as well as change notifications
103 * for state, errors, and for event handlers, all occur on the main JavaFX application
104 * thread. Accessing these properties from a background thread (including the
426 * // Return null at the end of a Task of type Void
427 * return null;
428 * }
429 * };
430 * </code></pre>
431 *
432 * <h3>A Task Which Returns An ObservableList</h3>
433 *
434 * <p>Because the ListView, TableView, and other UI controls and scene graph
435 * nodes make use of ObservableList, it is common to want to create and return
436 * an ObservableList from a Task. When you do not care to display intermediate
437 * values, the easiest way to correctly write such a Task is simply to
438 * construct an ObservableList within the <code>call</code> method, and then
439 * return it at the conclusion of the Task.</p>
440 *
441 * <pre><code>
442 * Task<ObservableList<Rectangle>> task = new Task<ObservableList<Rectangle>>() {
443 * @Override protected ObservableList<Rectangle> call() throws Exception {
444 * updateMessage("Creating Rectangles");
445 * ObservableList<Rectangle> results = FXCollections.observableArrayList();
446 * for (int i=0; i<100; i++) {
447 * if (isCancelled()) break;
448 * Rectangle r = new Rectangle(10, 10);
449 * r.setX(10 * i);
450 * results.add(r);
451 * updateProgress(i, 100);
452 * }
453 * return results;
454 * }
455 * };
456 * </code></pre>
457 *
458 * <p>In the above example, we are going to create 100 rectangles and return
459 * them from this task. An ObservableList is created within the
460 * <code>call</code> method, populated, and then returned.</p>
461 *
462 * <h3>A Task Which Returns Partial Results</h3>
463 *
464 * <p>Sometimes you want to create a Task which will return partial results.
465 * Perhaps you are building a complex scene graph and want to show the
466 * scene graph as it is being constructed. Or perhaps you are reading a large
506 * updateValue(v);
507 * }
508 * }
509 * a += b;
510 * b = a - b;
511 * }
512 * return a;
513 * }
514 * };
515 * </code></pre>
516 *
517 * <p>Suppose instead of updating a single value, you want to populate an ObservableList
518 * with results as they are obtained. One approach is to expose a new property on the Task
519 * which will represent the partial result. Then make sure to use
520 * <code>Platform.runLater</code> when adding new items to the partial
521 * result.</p>
522 *
523 * <pre><code>
524 * public class PartialResultsTask extends Task<ObservableList<Rectangle>> {
525 * // Uses Java 7 diamond operator
526 * private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults =
527 * new ReadOnlyObjectWrapper<>(this, "partialResults",
528 * FXCollections.observableArrayList(new ArrayList<Rectangle>()));
529 *
530 * public final ObservableList<Rectangle> getPartialResults() { return partialResults.get(); }
531 * public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty() {
532 * return partialResults.getReadOnlyProperty();
533 * }
534 *
535 * @Override protected ObservableList<Rectangle> call() throws Exception {
536 * updateMessage("Creating Rectangles...");
537 * for (int i=0; i<100; i++) {
538 * if (isCancelled()) break;
539 * final Rectangle r = new Rectangle(10, 10);
540 * r.setX(10 * i);
541 * Platform.runLater(new Runnable() {
542 * @Override public void run() {
543 * partialResults.get().add(r);
544 * }
545 * });
546 * updateProgress(i, 100);
547 * }
548 * return partialResults.get();
549 * }
550 * }
551 * </code></pre>
552 *
553 * <h3>A Task Which Modifies The Scene Graph</h3>
554 *
555 * <p>Generally, Tasks should not interact directly with the UI. Doing so
556 * creates a tight coupling between a specific Task implementation and a
557 * specific part of your UI. However, when you do want to create such a
558 * coupling, you must ensure that you use <code>Platform.runLater</code>
559 * so that any modifications of the scene graph occur on the
560 * FX Application Thread.</p>
561 *
562 * <pre><code>
563 * final Group group = new Group();
564 * Task<Void> task = new Task<Void>() {
565 * @Override protected Void call() throws Exception {
566 * for (int i=0; i<100; i++) {
567 * if (isCancelled()) break;
568 * final Rectangle r = new Rectangle(10, 10);
569 * r.setX(10 * i);
570 * Platform.runLater(new Runnable() {
571 * @Override public void run() {
572 * group.getChildren().add(r);
573 * }
574 * });
575 * }
576 * return null;
577 * }
578 * };
579 * </code></pre>
580 *
581 * <h3>Reacting To State Changes Generically</h3>
582 *
583 * <p>Sometimes you may want to write a Task which updates its progress,
584 * message, text, or in some other way reacts whenever a state change
585 * happens on the Task. For example, you may want to change the status
586 * message on the Task on Failure, Success, Running, or Cancelled state changes.
|
60 * A fully observable implementation of a {@link FutureTask}. {@code Task} exposes
61 * additional state and observable properties useful for programming asynchronous
62 * tasks in JavaFX, as defined in the {@link Worker} interface. An implementation
63 * of Task must override the {@link javafx.concurrent.Task#call()} method. This method
64 * is invoked on the background thread. Any state which is used in this method
65 * must be safe to read and write from a background thread. For example, manipulating
66 * a live scene graph from this method is unsafe and will result in runtime
67 * exceptions.
68 * </p>
69 * <p>
70 * Tasks are flexible and extremely useful for the encapsulation of "work". Because
71 * {@link Service} is designed to execute a Task, any Tasks defined by the application
72 * or library code can easily be used with a Service. Likewise, since Task extends
73 * from FutureTask, it is very easy and natural to use a Task with the java concurrency
74 * {@link java.util.concurrent.Executor} API. Since a Task is Runnable, you
75 * can also call it directly (by invoking the {@link javafx.concurrent.Task#run()} method)
76 * from another background thread. This allows for composition of work, or pass it to
77 * a new Thread constructed and executed manually. Finally, since you can
78 * manually create a new Thread, passing it a Runnable, it is possible to use
79 * the following idiom:
80 * </p>
81 * <pre><code>
82 * Thread th = new Thread(task);
83 * th.setDaemon(true);
84 * th.start();
85 * </code></pre>
86 * <p>
87 * Note that this code sets the daemon flag of the Thread to true. If you
88 * want a background thread to prevent the VM from existing after the last
89 * stage is closed, then you would want daemon to be false. However, if
90 * you want the background threads to simply terminate after all the
91 * stages are closed, then you must set daemon to true.
92 * </p>
93 * <p>
94 * Although {@link java.util.concurrent.ExecutorService} defines several methods which
95 * take a Runnable, you should generally limit yourself to using the <code>execute</code>
96 * method inherited from {@link java.util.concurrent.Executor}.
97 * </p>
98 * <p>
99 * As with FutureTask, a Task is a one-shot class and cannot be reused. See {@link Service}
100 * for a reusable {@link Worker}.
101 * </p>
102 * <p>
103 * Because the Task is designed for use with JavaFX GUI applications, it ensures
104 * that every change to its public properties, as well as change notifications
105 * for state, errors, and for event handlers, all occur on the main JavaFX application
106 * thread. Accessing these properties from a background thread (including the
428 * // Return null at the end of a Task of type Void
429 * return null;
430 * }
431 * };
432 * </code></pre>
433 *
434 * <h3>A Task Which Returns An ObservableList</h3>
435 *
436 * <p>Because the ListView, TableView, and other UI controls and scene graph
437 * nodes make use of ObservableList, it is common to want to create and return
438 * an ObservableList from a Task. When you do not care to display intermediate
439 * values, the easiest way to correctly write such a Task is simply to
440 * construct an ObservableList within the <code>call</code> method, and then
441 * return it at the conclusion of the Task.</p>
442 *
443 * <pre><code>
444 * Task<ObservableList<Rectangle>> task = new Task<ObservableList<Rectangle>>() {
445 * @Override protected ObservableList<Rectangle> call() throws Exception {
446 * updateMessage("Creating Rectangles");
447 * ObservableList<Rectangle> results = FXCollections.observableArrayList();
448 * for (int i=0; i<100; i++) {
449 * if (isCancelled()) break;
450 * Rectangle r = new Rectangle(10, 10);
451 * r.setX(10 * i);
452 * results.add(r);
453 * updateProgress(i, 100);
454 * }
455 * return results;
456 * }
457 * };
458 * </code></pre>
459 *
460 * <p>In the above example, we are going to create 100 rectangles and return
461 * them from this task. An ObservableList is created within the
462 * <code>call</code> method, populated, and then returned.</p>
463 *
464 * <h3>A Task Which Returns Partial Results</h3>
465 *
466 * <p>Sometimes you want to create a Task which will return partial results.
467 * Perhaps you are building a complex scene graph and want to show the
468 * scene graph as it is being constructed. Or perhaps you are reading a large
508 * updateValue(v);
509 * }
510 * }
511 * a += b;
512 * b = a - b;
513 * }
514 * return a;
515 * }
516 * };
517 * </code></pre>
518 *
519 * <p>Suppose instead of updating a single value, you want to populate an ObservableList
520 * with results as they are obtained. One approach is to expose a new property on the Task
521 * which will represent the partial result. Then make sure to use
522 * <code>Platform.runLater</code> when adding new items to the partial
523 * result.</p>
524 *
525 * <pre><code>
526 * public class PartialResultsTask extends Task<ObservableList<Rectangle>> {
527 * // Uses Java 7 diamond operator
528 * private ReadOnlyObjectWrapper<ObservableList<Rectangle>> partialResults =
529 * new ReadOnlyObjectWrapper<>(this, "partialResults",
530 * FXCollections.observableArrayList(new ArrayList<Rectangle>()));
531 *
532 * public final ObservableList<Rectangle> getPartialResults() { return partialResults.get(); }
533 * public final ReadOnlyObjectProperty<ObservableList<Rectangle>> partialResultsProperty() {
534 * return partialResults.getReadOnlyProperty();
535 * }
536 *
537 * @Override protected ObservableList<Rectangle> call() throws Exception {
538 * updateMessage("Creating Rectangles...");
539 * for (int i=0; i<100; i++) {
540 * if (isCancelled()) break;
541 * final Rectangle r = new Rectangle(10, 10);
542 * r.setX(10 * i);
543 * Platform.runLater(new Runnable() {
544 * @Override public void run() {
545 * partialResults.get().add(r);
546 * }
547 * });
548 * updateProgress(i, 100);
549 * }
550 * return partialResults.get();
551 * }
552 * }
553 * </code></pre>
554 *
555 * <h3>A Task Which Modifies The Scene Graph</h3>
556 *
557 * <p>Generally, Tasks should not interact directly with the UI. Doing so
558 * creates a tight coupling between a specific Task implementation and a
559 * specific part of your UI. However, when you do want to create such a
560 * coupling, you must ensure that you use <code>Platform.runLater</code>
561 * so that any modifications of the scene graph occur on the
562 * FX Application Thread.</p>
563 *
564 * <pre><code>
565 * final Group group = new Group();
566 * Task<Void> task = new Task<Void>() {
567 * @Override protected Void call() throws Exception {
568 * for (int i=0; i<100; i++) {
569 * if (isCancelled()) break;
570 * final Rectangle r = new Rectangle(10, 10);
571 * r.setX(10 * i);
572 * Platform.runLater(new Runnable() {
573 * @Override public void run() {
574 * group.getChildren().add(r);
575 * }
576 * });
577 * }
578 * return null;
579 * }
580 * };
581 * </code></pre>
582 *
583 * <h3>Reacting To State Changes Generically</h3>
584 *
585 * <p>Sometimes you may want to write a Task which updates its progress,
586 * message, text, or in some other way reacts whenever a state change
587 * happens on the Task. For example, you may want to change the status
588 * message on the Task on Failure, Success, Running, or Cancelled state changes.
|