'Emit function never collected in Kotlin Flow

I'm trying to have a function that does all the API calls and Room storing. But in this function, I have one emit that doesn't work.

fun getAPI() = flow {
    emit(State.Loading())
    // suspend function
    val response = safeApiCall{
        // retrofit request here
    }

    when (response) {
        is Success -> {
            // Emit here not working
            response.data?.let { emit(State.InsertOK(it)) }
            // Insert data in Room
            response.data?.let { insertQuery(it) }
        }
        is Error -> {
            emit(State.Error(response.error)
        }
    }
    
    emitAll(getQuery().map { State.Success(it) })
}

These values are collected in my ViewModel

private val _result = MutableLiveData<State<APIResult>>()
val result: LiveData<State<APIResult>>
        get() = _result 

fun getAPI( ) = viewModelScope.launch {
        repository.getAPI()
            .collect {
                _result .postValue(it)
            }
    }

I tried to have my DAO call after and before my emit but nothing changes. Am I doing something wrong with Flow that is not intended to be used like this?



Solution 1:[1]

The flow emit will work only in the launched context so not sure if somewhere you are launching into another context or something.

But here is some workaround. You can return MutableStateFlow and can collect as same as you do with normal flow no change at all but have to return MutableStateFlow at the function definition. Something like below. Replace api your response with the ResponseModel. MutableStateFlow is just like livedata but with benefits of flow so not much change you have to do.

fun myFlow() = MutableStateFlow<State<ResponseModel>> {
    val mutableFlow = MutableStateFlow<State<ResponseModel>>(State.Loading())

    val response = safeApiCall{
        // retrofit request here
    }

    when (response) {
        is Success -> {
            // Emit here not working
            response.data?.let { mutableFlow.value = State.InsertOK(it) }
            // Insert data in Room
            response.data?.let { insertQuery(it) }
        }
        is Error -> {
            mutableFlow.value = State.Error(response.error)
        }
    }
    
   // emitAll(getQuery().map { State.Success(it) }) //here also assign value accordingly
   return mutableFlow
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 vikas kumar