Reputation: 983
In TornadoFX I want to unsubscribe a custom event so that the receiver will never handle the unnecessary events again, and maybe avoid something like memory leaks, however, when I use the unsubscribe<MyEvent>
method in my code it doesn't work at all. Here is the part of my code:
object MyEventObj: FXEvent(EventBus.RunOn.BackgroundThread)
class MyEventBus(val personlist:List<PersonOld>): FXEvent()
class MyController: Controller()
{
init
{
subscribe<MyEventObj> {
unsubscribe<MyEventObj> {
println("Unsubscribe event!") //unsubscrib event and make sure the next code just runs once, but never works!
}
println("Event has received!")
val items = listOf(PersonOld("Name A", 20), PersonOld("Name B", 25))
fire(MyEventBus(items))
}
}
}
So, what is the problem? And how to use unsubscribe
in TornadoFX? Thanks for help me in advance!
Upvotes: 1
Views: 534
Reputation: 7297
The unsubscribe
function takes the event listener as it's only parameter. To be able to unsubscribe, you therefore need to save the listener as a member val so you can reference it. To make matters more interesting, you cannot reference this
inside the listener itself, so you need to call out to another function to be able to unsubscribe successfully. Here is a complete example:
object MyEvent : FXEvent()
class MyView : View() {
override val root = stackpane {
paddingAll = 100
button("Fire!") {
setOnAction {
fire(MyEvent)
}
}
}
val myListener: (MyEvent) -> Unit = {
alert(Alert.AlertType.INFORMATION, "Event received!", "This message should only appear once.")
stopListening()
}
init {
subscribe(myListener)
}
fun stopListening() = unsubscribe(myListener)
}
If it was possible to reference the listener from within itself we could have added an unsubscribe()
call directly inside the listener, but that's not possible, at least not with Kotlin 1.0.
EDIT: We just added a times = n
parameter to subscribe so you don't need to deal with unregistration yourself. By default your event listener will be triggered every time the event fires, but by passing 1
, you can unregistrer automatically after the first time. With this new feature, coming in TornadoFX 1.6.3, you can simply do this instead:
class MyView : View() {
override val root = stackpane {
paddingAll = 100
button("Fire!") {
setOnAction {
fire(MyEvent)
}
}
}
init {
subscribe<MyEvent>(times = 1) {
alert(Alert.AlertType.INFORMATION, "Event received!", "This message should only appear once.")
}
}
}
EDIT2: TornadoFX 1.6.3 will also introduce an EventContext
which the trigger operates on, so you will be able to do unsubscribe()
inside the event listener from the next version. Then you can do this as an alternative to the times
parameter:
subscribe<MyEvent> {
alert(Alert.AlertType.INFORMATION, "Event received!", "This message should only appear once.")
unsubscribe()
}
Upvotes: 2