RFR: JDK-8304439: Subscription based listeners [v13]

John Hendrikx jhendrikx at openjdk.org
Thu Jul 13 21:19:19 UTC 2023


On Thu, 13 Jul 2023 20:52:15 GMT, John Hendrikx <jhendrikx at openjdk.org> wrote:

>> 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.

I put your changes (that we agree upon so far) in #1177 

As I said I'm not sure about the description for the Subscription class, and it's not included yet, and so I also haven't yet removed the duplicated texts about GC-ability from the `subscribe` methods.

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1069#discussion_r1263061353


More information about the openjfx-dev mailing list