Home > other >  Rerun StateFlow When Filter Needs to Change?
Rerun StateFlow When Filter Needs to Change?

Time:05-20

I have a StateFlow containing a simple list of strings. I want to be able to filter that list of Strings. Whenever the filter gets updated, I want to push out a new update to the StateFlow.

class ResultsViewModel(
    private val api: API
) : ViewModel() {

  var filter: String = ""
  val results: StateFlow<List<String>> = api.resultFlow()
        .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
}

It's easy enough to stick a map onto api.resultFlow():

  val results: StateFlow<List<String>> = api.resultFlow()
        .map { result ->
            val filtered = mutableListOf<String>()
            for (r in result) {
                if (r.contains(filter)) {
                   filtered.add(r)
                }
            }
            filtered
        }
        .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())

But how do I get the flow to actually emit an update when filter changes? Right now, this only works with whatever the initial value of filter is set to.

CodePudding user response:

You could have the filter update another StateFlow that is combined with the other one. By the way, there's filter function that is easier to use than manually creating another list and iterating to get your results.

class ResultsViewModel(
    private val api: API
) : ViewModel() {

  private val filterFlow = MutableStateFlow("")

  var filter: String
    get() = filterFlow.value
    set(value) {
        filterFlow.value = value
    }

  val results: StateFlow<List<String>> = 
    api.resultFlow()
      .combine(filterFlow) { list, filter ->
          list.filter { it.contains(filter) }
      }
      .stateIn(viewModelScope, SharingStarted.Eagerly, emptyList())
}
  • Related