https://kotlinlang.org logo
Title
t

the great warrior

05/09/2023, 5:48 PM
Hi guys. A Flow from a DAO only completes when you cancel the coroutine that is collecting it. I want the flow to be completed when for loop is done. What should I do?
@AndroidEntryPoint
class RescheduleAlarmJobService : JobService() {

    @Inject lateinit var alarmRepository: AlarmRepository

    @Inject lateinit var scheduleAlarmManager: ScheduleAlarmManager

    val jobServiceScope = CoroutineScope(SupervisorJob())

    override fun onStartJob(p0: JobParameters?): Boolean {
        jobServiceScope.launch {
            alarmRepository.alarmsList.onCompletion {
                jobFinished(p0, false)
                jobServiceScope.cancel()
            }.buffer().collect { alarmList ->
                for (alarm in alarmList) {
                    if (alarm.isScheduled) {
                        scheduleAlarmManager.schedule(alarm)
                    }
                }
            }

        }
        return true
    }

    override fun onStopJob(p0: JobParameters?): Boolean {
        jobServiceScope.cancel()
        return false
    }
}
g

gildor

05/13/2023, 2:48 PM
Direct solution is to throw CancellationException, but what you really want is to use first() with filter:
val scheduledAlarms = flow.map { alarmList -> 
   alarmList.filter { alarm -> alarm.isScheduled() }
}.first() 
scheduledAlarms.forEach { schedule(it) }
Of I understand your case correctly (I mean it's the only loop in your code)
I have quite a lot of questions on your code though, maybe you trying to achieve something different Essentially if alarmsList is never complete, do not use onCompletion, it will not be called without manual cancellation, and instead of collect () use terminal operators, like first(), which automatically cancel flow when finish their work
t

the great warrior

05/17/2023, 2:27 PM
thanks so much Andrey Mischenko your answer works properly
g

gildor

05/17/2023, 3:29 PM
Glad that it helps, just a small correction to my first snippet, it probably makes sense (depending on required semantics of course) to filter items which do not have any scheduled alarms (using filter after map), so you will get first scheduled element, but depends on your case of course, maybe you want completely even if nothing is scheduled
t

the great warrior

05/18/2023, 7:47 PM
I appreciate your clarification