【问题标题】:How do I create a method for listeners?如何为侦听器创建方法?
【发布时间】:2021-09-12 17:29:37
【问题描述】:

我的更改监听器有一个生命周期,为了不将它们保存在内存中,我想我需要添加一个方法,例如 removeItemChangeListener 并调用它,例如,在 onClear 的方法中视图模型。据我所知,onClear 方法被覆盖为活动的onCreate。另外,在我看来,我需要将侦听器类型转换为接口。

MyItemsRepository.kt

interface MyItemsRepository {
    val items: List<ItemModel>

    fun setFavorite(itemModel: ItemModel, isFavorite: Boolean)

    fun addItemChangeListener(listener: () -> Unit)
}

ContentViewModel.kt

class ContentViewModel(
    private val repository: MyItemsRepository
) : ViewModel() {

    private val _items: MutableLiveData<List<ItemModel>> = MutableLiveData()
    val items: LiveData<List<ItemModel>>
        get() = _items

    var isFavorite: Boolean = false

    init {
        repository.addItemChangeListener {
            getItems()
        }
    }

    fun changeFavoriteState(item: ItemModel, favorite: Boolean) {
        repository.setFavorite(item, favorite)
    }

    fun getItems() {
        _items.value = if (isFavorite) {
            repository.items.filter { it.isFavorite }
        } else {
            repository.items
        }
    }

    class Factory : ViewModelProvider.Factory {
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            return ContentViewModel(MyItemsRepositoryImpl.getInstance()) as T
        }
    }
}

我需要您的帮助来编写代码。我心里明白怎么做,但我不知道怎么写。非常感谢您提供带有解释的书面示例。

【问题讨论】:

  • 我对你的实现感到困惑,你为什么要使用interface & listeners。您不能通过创建存储库类并将其视为本地数据源并使用它来实现您想要的任何东西吗?如果您正在关注任何教程,可能会在帖子中提及其链接。对于这么小的架构,您似乎正在增加复杂性。
  • 也许解释一下你的用例,你想在这里实现什么?
  • @ParagPawar 我正在回答您关于本地数据源的问题。事实是,我的任务是创建您在我的代码中看到的内容,而我现在才致力于纠正任何 cmets。我知道我的管理层已经安排好了一切,因此我只需要按照我上面写的去做。不需要重写监听器类型,可能,这些只是我的猜测。

标签: android kotlin listener viewmodel


【解决方案1】:

也许尝试调用 removeItemChangeListener 方法,就像调用 setFavorite 一样,只需从 ViewModel 的 onCleared 方法调用它

class ContentViewModel(
    private val repository: MyItemsRepository
) : ViewModel() {

    ...

    override fun onCleared() {
        super.onCleared()
        repository.removeItemChangeListener()
    }

}

在您的存储库中,它会是这样的:

override fun removeItemChangeListener() {
    listeners.clear()
}

你不能真正做这样的事情:listeners.remove(listener),因为无论如何你要如何将侦听器从 ViewModel 传递到存储库?

在接口MyItemsRepository中添加removeItemChangeListener方法

interface MyItemsRepository {
    
    ...

    fun removeItemChangeListener()
}

同样,还没有真正测试过它,但它应该可以工作。

编辑:

不同的方法:

class ContentViewModel(
    private val repository: MyItemsRepository
) : ViewModel() {

    var listener = {
        getItems()
    }

    init{
        repository.addItemChangeListener {
            listener
        }
    }

    ...

    override fun onCleared() {
        super.onCleared()
        repository.removeItemChangeListener(listener)
    }

}

在您的存储库中,它会是这样的:

override fun removeItemChangeListener(listener: () -> Unit) {
    listeners.remove(listener)
}

在接口MyItemsRepository中添加removeItemChangeListener方法

interface MyItemsRepository {
    
    ...

    fun removeItemChangeListener(listener: () -> Unit)
}

我不确定这是否可行。试试看,然后告诉我。

【讨论】:

  • 在视图模型中尝试调用removeItemChangeListener()函数时,出现错误“Unresolved reference: removeItemChangeListener”。
  • 检查removeItemChangeListener()的方法是否正确,可能检查拼写、语法。或者只是复制粘贴,我写的代码
  • 不,它不会起作用,明白问题所在。我会编辑答案。
  • Android Studio 提出:创建抽象函数'MyItemsRepository.removeItemChangeListener'
  • 已编辑答案请立即尝试
【解决方案2】:

它看起来就像你的 addItemChangeListener 函数,除了它应该调用 remove 而不是 add。不确定您不确定概念的哪一部分。将其定义为接口是可选的。接口可能有助于更好地传达听众的目的,但不会改变功能。如果您这样做,您可能希望将其定义为 fun interface,因为如果您可以使用 lambda 来表示接口,它们会更有趣。

话虽如此,如果您对协程持开放态度,那么您的 repo 会更容易公开 Flow。然后如果 ViewModel 订阅了 Flow,超出范围时会自动取消订阅。

【讨论】:

    猜你喜欢
    • 2016-12-14
    • 1970-01-01
    • 1970-01-01
    • 2013-03-04
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多