On Sun, 9 Jul 2023 23:13:20 GMT, Jose Pereda <jper...@openjdk.org> wrote:

>> There is no need, the returned `Subscription` is implemented using a lambda 
>> that captures the listener (as it needs it to call `removeListener`).  As 
>> long as you have the `Subscription` referenced, it can't get GC'd.  If you 
>> let the `Subscription` get GC'd, then you'd lose your means to unsubscribe 
>> the listener, just like if you lost the reference to the listener itself, 
>> you would never be able to remove it anymore.
>> 
>> Weak listeners I would not recommend to use in new code if you can avoid it. 
>>  They're unpredictable as to when they're removed exactly, and can still 
>> receive notifications when your application may be in a state where you 
>> don't expect them anymore.
>> 
>> The `Subscription` interface is in fact intended to make management of 
>> listeners easier so you can rely less on weak listeners.  One pattern I can 
>> really recommend to use is to automatically disable listeners when the UI 
>> they belong with becomes invisible, for example:
>> 
>>     private Subscription subscription = Subscription.EMPTY;
>> 
>>     node.sceneProperty()
>>       .flatMap(Scene::windowProperty)
>>       .flatMap(Window::showingProperty)
>>       .subscribe(visible -> {
>>             if (visible) {
>>                   subscription = Subscription.combine(
>>                        // create subscriptions (to external resources) here 
>> as we just became visible!
>>                   );
>>             }
>>             else {
>>                   // we became invisible, remove listeners (from external 
>> resources) to remove hard references that 
>>                   // may keep the UI referenced; the other branch will 
>> restore them if the UI becomes visible again
>>                   subscription.unsubscribe();  // unsubscribes everything in 
>> one go
>>             }
>>       });
>>       
>> Or you can use `ObservableValue#when` to do something similar, not requiring 
>> subscriptions.
>> 
>> I suspect it may also prove a useful pattern for `Skin`s that have a 
>> specific lifecycle.  They can register listeners (and combine in a single 
>> subscription) in their constructor / initializer, and remove them all in 
>> their `dispose` method.
>
> Yes, `flatMap` or `when` are great for those cases, so the pattern with the 
> new `subscribe` proposal seems quite useful.

I missed the `orElse(false)` in the example above, which deals with scene being 
`null`.  Full example should be:


private Subscription subscription = Subscription.EMPTY;

node.sceneProperty()
  .flatMap(Scene::windowProperty)
  .flatMap(Window::showingProperty)
  .orElse(false)
  .subscribe(visible -> {
        if (visible) {
              subscription = Subscription.combine(
                   // create subscriptions (to external resources) here as we 
just became visible!
              );
        }
        else {
              // we became invisible, remove listeners (from external 
resources) to remove hard references that 
              // may keep the UI referenced; the other branch will restore them 
if the UI becomes visible again
              subscription.unsubscribe();  // unsubscribes everything in one go
        }
  });

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

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

Reply via email to