Search code examples
androidkotlinlistenerviewmodel

How do I create a method for listeners?


My listeners to changes have a lifetime and in order not to keep them in memory, I think I need to add a method, for example, removeItemChangeListener and call it, for example, in the onClear method of the view model. As far as I know, the onClear method is overridden as onCreate for the activity. Also, it seems to me that i need to convert the listener type to an interface.

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

I need your help writing the code. I mentally understand how to do it, but I don't know how to write it. I would be very grateful for a written example with an explanation.


Solution

  • Maybe try calling the method removeItemChangeListener the same way you're calling setFavorite, Just call it from the onCleared method of a ViewModel

    class ContentViewModel(
        private val repository: MyItemsRepository
    ) : ViewModel() {
    
        ...
    
        override fun onCleared() {
            super.onCleared()
            repository.removeItemChangeListener()
        }
    
    }
    

    And in your repository it would be something like this:

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

    You cannot really do something like this: listeners.remove(listener) because how are you going to pass the listener from ViewModel to repository anyway?

    Add the removeItemChangeListener method in the interface MyItemsRepository

    interface MyItemsRepository {
        
        ...
    
        fun removeItemChangeListener()
    }
    

    Again, haven't really tested it, but it should work.

    EDIT:

    Different approach:

    class ContentViewModel(
        private val repository: MyItemsRepository
    ) : ViewModel() {
    
        var listener = {
            getItems()
        }
    
        init{
            repository.addItemChangeListener {
                listener
            }
        }
    
        ...
    
        override fun onCleared() {
            super.onCleared()
            repository.removeItemChangeListener(listener)
        }
    
    }
    

    And in your repository it would be something like this:

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

    Add the removeItemChangeListener method in the interface MyItemsRepository

    interface MyItemsRepository {
        
        ...
    
        fun removeItemChangeListener(listener: () -> Unit)
    }
    

    I'm not really sure if this will work. Try it out and let me know.