如何在Kotlin中设置变量的监听器

14

如何在 Kotlin 中设置接口监听器以侦听变量更改。我已经成功地在 Java 中实现了以下操作,但在 Kotlin 中遇到了问题:

接口:

public interface InterfaceRefreshList
    {
    public void refreshListRequest();
    }

包含监听器的类:

public class SignalChange
    {
    private static boolean refreshListSwitch;
    private static List<InterfaceRefreshList> refreshListListeners = new ArrayList<>();
    public static void setRefreshList(boolean value)
    {
    refreshListSwitch = value;
    for(InterfaceRefreshList l : refreshListListeners)
        l.refreshListRequest();
    }
    public static void addRefreshListListener(InterfaceRefreshList l)
        {
        refreshListListeners.add(l);
        }
    }

监听器正在监听的类:

public class FragmentBrowse extends Fragment
{
    public FragmentBrowse() /// Constructor
        {
        SignalChange.addRefreshListListener(() -> refreshList());
        }
    refreshList()
    {
    // do something
    }
}

发出变更信号:

SignalChange.setRefreshList(true);

我可以设置界面和信号类:

class SignalChange
{
    private var refreshListSwitch: Boolean = false
    var setSwitch: Boolean
        get() = refreshListSwitch
        set(value)
        {
            refreshListSwitch = value
        }

    private var refreshListListeners = ArrayList<InterfaceRefreshPersonsList>()
    fun sendRefreshSignal()
    {
        for(l in refreshListListeners) l.refreshPersonsList()
    }

    fun addRefreshListListener(l: InterfaceRefreshPersonsList)
    {
        refreshListListeners.add(l)
    }

}

但是我无法在FragmentBrowse类中设置监听器。片段类不允许构造函数。


你遇到了哪些问题?为什么不直接在你的Java代码上运行Java转Kotlin转换器呢? - yole
转换器并不像那样简单。例如,我必须编写私有变量的静态setter:private var refreshListSwitch: Boolean = false var setSwitch: Boolean get() = refreshListSwitch set(value) { refreshListSwitch = value } - Samuel
你为什么要这样做?这看起来完全没有必要。无论如何,你没有回答你在Kotlin代码中具体遇到了哪些问题。 - yole
请查看编辑后的代码。 - Samuel
添加监听器的代码需要放置在初始化块中。IntelliJ IDEA中内置的Java到Kotlin转换器可以自动执行此转换。 - yole
我已经在init块中尝试过并添加了SignalChange的实例:signalChange = SignalChange(),但以下代码未转换:signalChange.addRefreshListListener(() -> refreshList()); - Samuel
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
19

您可以使用内置的 Kotlin 代理,例如:

object SignalChange {
    var refreshListListeners = ArrayList<InterfaceRefreshList>()

    // fires off every time value of the property changes
    var property1: String by Delegates.observable("initial value") { property, oldValue, newValue ->
        // do your stuff here
        refreshListListeners.forEach { 
            it.refreshListRequest()
        }
    }
}

interface InterfaceRefreshList {
    fun refreshListRequest()
}

像这样添加监听器:

SignalChange.refreshListListeners.add(object : InterfaceRefreshList {
    override fun refreshListRequest() {
        refreshList()
    }
})

或者(OR)

你可以使用lambda代替接口:

object SignalChange {
    var refreshListListeners = ArrayList<() -> Unit>()

    // fires off every time value of the property changes
    var property1: String by Delegates.observable("initial value") { property, oldValue, newValue ->
        // do your stuff here
        refreshListListeners.forEach {
            it()
        }
    }
}

要添加监听器只需调用:

SignalChange.refreshListListeners.add(::refreshList)
//or
SignalChange.refreshListListeners.add { refreshList() }

fun refreshList() {

}

通过发布的Java代码,我能够从程序的任何地方发出信号变更。Delegates.observable能做到这一点吗? - Samuel
我编辑了我的回答。当您将值设置为 property1 时,Delegates.observable 将触发并在每个侦听器上调用 refreshListRequest() - Sergio
这似乎与fun sendRefreshSignal() for(l in refreshListListeners) l.refreshPersonsList()相同,但我遇到的问题是如何从FragmentBrowse类中调用:fun addRefreshListListener(l: InterfaceRefreshPersonsList) refreshListListeners.add(l)。 - Samuel
似乎你需要将 SignalChange 实现为 Singleton。然后你就可以像这样添加监听器了。我已经编辑了我的回答,现在 SignalChange 是一个 Singleton - Sergio
你给了我们两个答案,这很好。其中一个比另一个更好吗? - Jevon

13

1
谢谢。你如何为myVariableName分配一个类型?我尝试了myVariableName: String by Delegates....但它不起作用。 - Jack'
2
哦,我明白了。将0分配为初始值会自动将myVariableName设置为Int类型。因此,我们应该对于字符串执行myVariableName by Delegates.observable("Initial Text") - Jack'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,