RFR: JDK-8304439: Subscription based listeners [v13]
John Hendrikx
jhendrikx at openjdk.org
Thu Jul 13 20:55:21 UTC 2023
On Thu, 13 Jul 2023 01:24:12 GMT, Nir Lisker <nlisker at openjdk.org> wrote:
>> John Hendrikx has updated the pull request incrementally with one additional commit since the last revision:
>>
>> Fix ObservableSubscriptionsTest
>
> modules/javafx.base/src/main/java/javafx/beans/Subscription.java line 33:
>
>> 31: /**
>> 32: * A subscription encapsulates how to cancel it without having
>> 33: * to keep track of how it was created.
>
> I would like to see some more info here, like what it is and how it's used, and a note on comparison with listeners. Taking a page out of `ChangeListener`, I took a stab at it:
>
>
> Executes code on change or invalidation events. A {@code Subscription} can be created by subscribing to invalidation
> events on an {@code Observable} using {@link Observable#subscribe(Runnable)}
> and to change events on an {@code ObsefvableValue} using {@link Observable#subscribe(Consumer)}
> and {@link Observable#subscribe(BiConsumer)}. It can be unsubscribed using {@link #unsuscribe}.
> <p>
> Subscriptions don't block the the {@code Observable} from being garbage collected, and will be collected with
> it (if they are not subscribed on other {@code Observable}s, see below). However, since {@code Observable}s
> blocks their subscriptions from being GC'd, {@code unsuscribe()} must be called if they are to be eligible for
> GC before the {@code Observable} is. Consider creating a derived {@code ObservableValue}
> using {@link #when(ObservableValue)} and subscribing on this derived observable value
> to automatically decouple the lifecycle of the subscriber from the original {@code ObservableValue}
> when some condition holds:
> {@code
> obs.when(cond).subscribe(...)
> }
> <p>
> Subscriptions can also be combined using {@link #combine} and {@link #and}, which allows for
> multiple subscriptions to be unsubscribed together. This is useful when they share the same lifecycle,
> which is usually the case when they are subscribed on the same {@code Observable}.
> <p>
> The same subscriber can be subscribed to multiple {@code Observable}s, including more than once on the
> same {@code Observable}, in which case it will be executed more than once. That is, no uniqueness check is made.
> <p>
> {@code Subscription}s behave similarly to {@link InvalidationListener}s and {@code ChangeListener}s. An
> advantage of {@code Subscription} is that it encapsulates how to cancel it without having to keep track of
> how it was created.
>
>
> This will also alleviate some repeated verbosity in the subscribe methods.
I'm not entirely sure about this; the `Subscription` interface is pretty neutral in how it can be used, and does not have any direct link to observables at all; it's more of a token that you get that can be used to cancel a previous action, it doesn't actively do anything (unless you count the wrapper that it puts around the provided function).
As it is, they don't even need to be associated with `Observable` or `ObservableValue` at all. Just as easily you could do:
FileInputStream inputStream = .. ;
Subscription combined = Subscription.combine(
property.subscribe(this::invalidated),
() -> inputStream.close()
);
combined.subscribe(); // closes input stream and removes invalidations subscriber
Although I think it is a good description, I'm not sure it belongs on this class.
-------------
PR Review Comment: https://git.openjdk.org/jfx/pull/1069#discussion_r1263043937
More information about the openjfx-dev
mailing list