1

I have an IOTCamera function inside viewModel with Loop. The function should repeatedly call the repository GET function based on the "selectedSlot" parameter with a delay of 1 minute. My problem here is the loop(repeat()) is not working properly. It's working for the first iteration. But the second iteration never gets called.

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

The repository function will call the Retrofit GET API and it will collect the data.

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

Please update if anyone know the reason for this.

Nithinjith
  • 1,775
  • 18
  • 40

1 Answers1

1

The call to collect never returns. If you just need to get a single value and end collecting then you should call first() instead.

Like this:

val data = repository.getIOTCameraData(1, 10).asFlow().first { 
    responseStatusIdentification(it)
}
_iotCameraData.postValue(data.data)
niqueco
  • 2,261
  • 19
  • 39
  • But in this case, the getIOTCameraData suspend function may emit two times. The first emit will be the loading status and the remaining one is either success or an error from the HTTP response. responseStatusIdentification() function is actually handling the loading status. So my question is whether the .first() will return twice? – Nithinjith May 28 '21 at 04:25
  • The terminal operator returns the first element emitted by the flow and then cancels the flow's collection. In my understanding, the .first() will cancel the remaining flows. – Nithinjith May 28 '21 at 04:36
  • 1
    I've edited my reply to filter out unsuccesful response. I invented a `isSucces` property for that, but that is maybe your `responseStatusIdentification()` function. EDIT: I've just assumed that. – niqueco May 28 '21 at 04:36
  • I tcan be a little better by just using the `first()` function that takes a predicate... I'll edit the reply =) – niqueco May 28 '21 at 12:49