【问题标题】:How to unsubscribe events in TornadoFX?如何取消订阅 TornadoFX 中的事件?
【发布时间】:2017-07-16 21:18:36
【问题描述】:

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

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

【问题讨论】:

    标签: java events kotlin unsubscribe tornadofx


    【解决方案1】:

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

    【讨论】:

    • 这使得一些代码添加和重写,终于我明白了!谢谢,它已经在我的测试代码中工作了。
    • 太棒了 :) 你可能想在 1.6.3 发布后重新访问它以进一步减少样板:)
    • 太好了!!迫不及待想要查看即将推出的新版本和新功能,终于可以按自己的方式使用了...(∩_∩)
    猜你喜欢
    • 2017-02-12
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 2020-11-11
    • 2014-02-15
    • 2011-08-14
    • 1970-01-01
    相关资源
    最近更新 更多