#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
?