1

在 TornadoFX 中,我想取消订阅一个自定义事件,这样接收者就不会再处理不必要的事件,并且可能避免像内存泄漏这样的事情,但是,当我unsubscribe<MyEvent>在我的代码中使用该方法时,它根本不起作用。这是我的代码的一部分:

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))
        }
    }
}

那么,问题是什么?以及如何unsubscribe在 TornadoFX 中使用?感谢您提前帮助我!

4

1 回答 1

2

unsubscribe函数将事件侦听器作为它的唯一参数。因此,为了能够取消订阅,您需要将侦听器保存为成员 val,以便您可以引用它。为了使事情更有趣,您不能this在侦听器本身内部引用,因此您需要调用另一个函数才能成功取消订阅。这是一个完整的例子:

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)

}

如果可以从自身内部引用侦听器,我们可以unsubscribe()直接在侦听器内部添加一个调用,但这是不可能的,至少在 Kotlin 1.0 中不行。

编辑:我们刚刚添加了一个times = n参数来订阅,所以您不需要自己处理注销。默认情况下,每次事件触发时都会触发您的事件侦听器,但是通过传递1,您可以在第一次之后自动取消注册。使用 TornadoFX 1.6.3 中的这个新功能,您可以简单地执行以下操作:

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 还将引入EventContext触发器操作的一个,因此您将能够unsubscribe()在下一个版本的事件侦听器中进行操作。然后,您可以将其作为times参数的替代方法:

subscribe<MyEvent> {
    alert(Alert.AlertType.INFORMATION, "Event received!", "This message should only appear once.")
    unsubscribe()
}
于 2017-02-26T09:52:40.200 回答