Search code examples
androidkotlinviewmodel

How to convert Flow to List in ViewModel?


I got a 200 code and I see loading/error but I can't get a success state.
How to convert Flow to List in ViewModel?

fun loadUsers() = viewModelScope.launch {
    _uiState.value = UiState.LOADING
    try {
        val users = withContext(Dispatchers.IO) { useCase.invoke() }
        _uiState.value = UiState.SUCCESS(users) // **i get an error Required:List<UsersModel> Found: Flow<List<UsersModel>>**
    } catch (e: Exception) {
        _uiState.value = UiState.FAILURE(e.localizedMessage)
    }
}

override suspend fun getAllUsers(): Flow<List<UsersModel>> = flow {

    val response = randomUserApi.getResults()

    if (response.isSuccessful && response.body() != null) {
        response.body()?.let {
            response.body()!!.results.map {
                it.toModel()
            }
        }
    }
} 

sealed class UiState {
    data class SUCCESS(val users: List<UsersModel>) : UiState()

Solution

    1. Flow is inappropriate to use here in the first place because you are retrieving a single thing, one time.
    2. If you were using a flow, it shouldn’t be returned by a suspend function, since a flow is created immediately without doing any work synchronously. But actually since you are retrieving one thing immediately, what you should be using is a suspend function that returns a list directly or throws an error.
    3. If you were going to use a flow, this flow doesn’t do anything because you never emit anything from the builder lambda.
    4. You do not need to specify a dispatcher to call a suspend function. Suspend functions do not block unless you incorrectly put blocking code in the suspend function without wrapping it in an appropriate dispatcher.

    Here is corrected use case code:

    override suspend fun getAllUsers():List<UsersModel> {
        val response = randomUserApi.getResults()
        val responseBody = response.body()
    
        if (response.isSuccessful && responseBody != null) {
            return responseBody.results.map { it.toModel() }
        }
        throw IOException(
            "Failed to retrieve user model: " + 
                response.errorBody().toString()
        )
    }