I have a control that should react to some kinds of events, and therefore adds itself to a listener list in the constructor. Of course it should remove itself as well, but while Swing and RCP have dispose()
methods, I can't seem to find any in JavaFx.
public class MyTable extends TableView implements MyListener {
public MyTable () {
Events.addListener(this);
}
public disposeOrSomething() {
Events.removeListener(this);
}
// actual implementation of MyListener
}
Don't get hung up on the static Events
class, thought. It does not matter to me if the control adds itself to something static or not. What is important: there are two parts of an application that are not connected except for a general event system. So when the listening part vanishes (e.g. the window gets closed) of course the listener should be disposed.
Up until know, when the listener was directly connected to the life cycle of the control, the control registered it. But now in JavaFX that won't work, and due to loosely coupled FXML files I can't see anyone else who has the necessary information (the control and the "window close event") either.
So what is a good way to clean up after controls when they are no longer used?
As said before, I recommend not using a global event bus and, as suggested by @Puce, not registering listeners on anything else than encapsulated objects.
Anyway, here is a way to automatically subscribe to events only when a certain Node
is showing (i.e. automatically unsubscribe when the node is removed from the scene or the window is closed). This solution makes use of ReactFX, namely the helper EventStream#conditionOnShowing method.
Since you didn't provide the signature of MyListener
, I will assume this signature:
@FunctionalInterface
interface MyListener {
void handle(MyEvent event);
}
import org.reactfx.EventStream;
import org.reactfx.EventStreamBase;
import org.reactfx.Subscription;
public class MyTable extends TableView {
public MyTable () {
// Since you are using some custom event dispatching mechanism,
// the first step is to convert that into a ReactFX EventStream.
EventStream<MyEvent> events = new EventStreamBase<MyEvent>() {
@Override protected Subscription observeInputs() {
MyListener l = event -> notifyObservers(event);
Events.addListener(l);
return () -> Events.removeListener(l);
}
};
// Now the interesting part: events will not be observed whenever
// this MyTable is not part of a showing Window.
events.conditionOnShowing(this).subscribe(event -> this.handleEvent(Event));
}
private void handleEvent(MyEvent) {
/* ... */
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments