Проблема с живыми данными внутри цикла

#android #android-livedata #kotlin-coroutines #android-viewmodel #android-livedata-transformations

Вопрос:

У меня есть функция IOTCamera внутри ViewModel с циклом. Функция должна повторно вызывать функцию GET репозитория на основе параметра «selectedSlot» с задержкой в 1 минуту. Моя проблема здесь в том, что цикл(повтор()) работает неправильно. Это работает для первой итерации. Но вторая итерация никогда не вызывается.

   fun getIOTCameraData(repository: MainRepository, selectedSlot: Int)= viewModelScope.launch(Dispatchers.Default){
        repeat(selectedSlot){
            repository.getIOTCameraData(1, 10).asFlow().collect {data->
                if (responseStatusIdentification(data)) {
                    _iotCameraData.postValue(data.data)//Update live data instance for UI
                }
            }
            delay(60000)
        }
    }
 

Функция репозитория вызовет API Retrofit GET, и он будет собирать данные.

  suspend fun getIOTCameraData(page: Int, perPage: Int) = liveData<Resource<IOTCameraResponse>> {
        emit(Resource.loading())
        try {
            val response = iotCameraService?.getIOTCameraData(token = IOT_CAMERA_AUTH, page = page, perPage = perPage)
            emit(Resource.success(response))
        } catch (e: Exception) {
            emit(Resource.error(e.message.toString()))
        }
    }
 

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

Ответ №1:

Призыв collect никогда не возвращается. Если вам просто нужно получить одно значение и завершить сбор, вам следует позвонить first() вместо этого.

Подобный этому:

 val data = repository.getIOTCameraData(1, 10).asFlow().first { 
    responseStatusIdentification(it)
}
_iotCameraData.postValue(data.data)
 

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

1. Но в этом случае функция getIOTCameraData suspend может выдавать два раза. Первым сообщением будет статус загрузки, а оставшимся — либо успех, либо ошибка в HTTP — ответе. Функция responseStatusIdentification() фактически обрабатывает состояние загрузки. Поэтому мой вопрос в том, вернется ли .first() дважды?

2. Оператор терминала возвращает первый элемент, испускаемый потоком, а затем отменяет сбор потока. В моем понимании,. first() отменит оставшиеся потоки.

3. Я отредактировал свой ответ, чтобы отфильтровать неудачный ответ. Я изобрел isSucces свойство для этого, но, возможно, это ваша responseStatusIdentification() функция. ПРАВКА: Я только что предположил это.

4. Я могу быть немного лучше, просто используя first() функцию, которая принимает предикат… Я отредактирую ответ =)