0

Imagine following scenario: I open Search View and SearchViewModel is initialized

class SearchViewModel(
    usecase: Usecase
) : ViewModel() {

    init {
        viewModelScope.launch {
            usecase.initialize()
        }

    }

    fun search(query: String) = viewModelScope.launch {
        usecase.search(query)
    }
}

User start typing characters calling search

class UseCase(
   private val dataSource: DataSource
   private val store: Store
) {

    private val searchQueryEmitter = MutableStateFlow<String>("") // 2 change to MutableSharedFlow
    private val searchQuery = searchQueryEmitter
        .mapLatest { query -> dataSource.search(query) }
        .onEach { store.update(it) } 
        .launchIn(CoroutineScope(Dispatchers.Default)) // 1 comment

    suspend fun search(query: String) {
        searchQueryEmitter.emit(query)
    }

    override suspend fun initialize() {
//        searchQuery.launchIn(CoroutineScope(Dispatchers.Default)) // > Emit only initial value
//        searchQuery.collect() // > Emit only initial value
    }
}

Flow emits first item "" and next items according to query value

PROBLEM:

  1. I don't understand if we comment launchIn (1), and call it later in initialize() method, then exactly the same searchQuery.launchIn(...) or searchQuery.collect() cause issue - flow emits only first item "", but calling search with query doesn't trigger emission of next items.
  2. If we change StateFlow to SharedFlow no items will be emitted in any case.
murt
  • 3,790
  • 4
  • 37
  • 48

1 Answers1

0

The problem was in ViewModel. I was using two different instances of usecase. The one passed in parameter was used in init while the second one came from import

so the desired case with

override suspend fun initialize() {
   searchQuery.collect() 
}

is working right now

murt
  • 3,790
  • 4
  • 37
  • 48