-
Notifications
You must be signed in to change notification settings - Fork 47
Subscribing to EventStreams
This page assumes that the reader has already read EventStream Intro and Basic Usage and is thus familiar with basic EventStream knowledge.
This page overviews the various ways one can subscribe to an EventStream.
Note: Subscriptions will not be managed in the following examples. It is assumed that the reader already understands how to manage Subscription objects returned from subscribe-related methods.
The following code will be used for the examples below. When needed, examples will provide additional content.
@Override
public void start(Stage primaryStage) {
Pane pane = new Pane();
Scene scene = new Scene(pane, 400, 400);
primaryStage.setScene(scene);
primaryStage.show();
EventStream<MouseEvent> sceneClicks = EventStreams.eventsOf(scene, MouseEvent.MOUSE_CLICKED);
}
Let's say that sceneClicks was initialized. Then, for the rest of the life of the program, nothing ever subscribes to sceneClicks. If this occurs, there are no memory leaks. What? How!? Because sceneClicks only starts observing its inputs/dependencies when something subscribes to it. Thus, all EventStream objects observes their inputs/dependencies lazily!
Let's say the following dashes "---" represents an EventStream and "S" is used to show that something has subscribed, and "#" is used to show that an event should be emitted by the EventStream:
----1-----2-----3------4------S----5---6----7-8----9---->
EventStream
objects are Cold Observables by default, so the subscriber will only get notified of events 5-9. It will never know about events 1-4. There are ways to make EventStream objects appear to be Hot Observables, but that will be covered elsewhere.
These methods all return a Subscription
object that should be managed and unsubscribed when no longer needed.
-
subscribe(Consumer c): runs
c
whenever the EventStream emits a new event.
// basic subscribe method
sceneClicks.subscribe(click -> System.out.println("Mouse Event was: " + click.toString());
These methods unsubscribe after so many events have been emitted from the EventStream.
-
subscribeFor(int n, Consumer c): same as
subscribe()
except auto-unsubscribes aftern
times.
// subscribe for 5 times
sceneClicks.subscribeFor(5, click -> System.out.println("This message will be printed 5 times!");
-
subscribeForOne(Consumer c): shortcut for
subscribeFor(1, c)
.
// Only do once!
sceneClicks.subscribeForOne(click -> System.out.println("I only want to display this message once!")
Sometimes, one might want to write:
Circle circle = new Circle();
EventStream<Double> radiusValues = ...;
radiusValues.subscribe(radius -> circle.setRadius(radius));
Rather than doing this, one should use the feedTo()
method:
- feedTo(): feeds the Event emitted from an EventStream to the WriteableProperty or EventSink
Circle streamCircle = new Circle();
Circle circle = new Circle();
EventStream<Double> widthValues = EventStreams.nonNullValuesOf(streamCircle.widthProperty());
// feed the widthValue to the other circle's radius.
widthValues.feedTo(circle.radiusProperty());
Sometimes, one wants an EventStream to observe its inputs/dependencies even when one doesn't want any code to run when an EventStream emits an Event. This would probably be used in EventStream Composition, a topic that will be covered later. In this situation, one would use the pin()
method.
- pin(): forces the EventStream to observe its inputs/dependencies.
Rectangle rectangle = new Rectangle(50, 50, Color.BLACK);
EventStream<Double> layoutYValues = EventStreams.nonNullValuesOf(rectangle.layoutYProperty());
// at this point, if rectangle's layoutY value changes, layoutYValues wouldn't emit an event
// because it's lazy.
layoutYValues.pin();
// now layoutYValues will emit an Event every time rectangle's layoutY value changes.