Функция Emit никогда не собиралась в Kotlin Flow

#android #kotlin #flow

#Android #kotlin #kotlin-flow

Вопрос:

Я пытаюсь создать функцию, которая выполняет все вызовы API и сохраняет номер. Но в этой функции у меня есть одна, emit которая не работает.

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

Эти значения собраны в моей ViewModel

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

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

Я пытался вызвать свой DAO после и до моего emit , но ничего не изменилось.
Я делаю что-то не так с потоком, который не предназначен для использования подобным образом?

Комментарии:

1. хорошо. можете ли вы подтвердить одну вещь, что safeApiCall не является асинхронным вызовом или чем-то другим потоку внутри функции myFlow ().

2. это функция приостановки

3. Не могли бы вы вставить код со стороны сбора, возможно?

4. Спасибо за обновление! Я подозреваю, что myFlow() — это repository.getAPI()?

5. Да! Я исправлю это

Ответ №1:

Поток emit будет работать только в запущенном контексте, поэтому не уверен, что где-то вы запускаете в другой контекст или что-то в этомроде.

Но вот некоторое обходное решение. Вы можете вернуть MutableStateFlow и можете собирать так же, как и в обычном потоке, без каких-либо изменений вообще, но должны возвращать MutableStateFlow в определении функции. Что-то вроде приведенного ниже. Замените свой ответ api на ResponseModel. MutableStateFlow похож на livedata, но с преимуществами flow, поэтому вам не нужно вносить особых изменений.

 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
}
  

Комментарии:

1. Я добавил область действия сопрограммы, потому что у меня есть приостановленные функции. Эмиссия вызывается, но мои функции приостановки больше не работают

2. Когда использовать value и когда использовать emit ?