I have some stateFlows which are linked:
val _currentDay = MutableStateFlow<Day>(Day())
val currentDay: StateFlow<Day> = _currentDay
val currentWeek = currentDay
.map { day -> getWeekFrom(day) }
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(5000),
initialValue = Week(currentDay.value),
)
val weekSchedule: StateFlow<ScheduleLoadingState> = currentWeek
.flatMapLatest { week -> getWeekSchedule(week) }
.stateIn(
scope = viewModelScope,
SharingStarted.WhileSubscribed(5000),
initialValue = ScheduleLoadingState.Loading,
)
@OptIn(FlowPreview::class)
val daySchedule: StateFlow<ScheduleLoadingState> = weekSchedule
.combine(currentDay) { weekschedule, day ->
getDayScheduleFromWeekSchedule(day, weekschedule)
}
.stateIn(
scope = viewModelScope,
SharingStarted.WhileSubscribed(5000),
initialValue = ScheduleLoadingState.Loading,
)
So when the day changes, the week is recalculated and may be updated when the day is in a new week. When the week is updated, the getWeekSchedule() function retrieves the new weekschedule from database and network. And at last the dayschedule is extracted from the weekschedule if the weekschedule is changed or the day within the week is changed.
But when the day is changed to a new week, the dayschedule is updated from the current weekschedule, then the weekschedule is updated and then the dayschedule is updated from the new weekschedule. The first update of the dayschedule is actually a false schedule as the weekschedule is not yet updated.
I would like to update the dayschedule only when the weekschedule is updated OR (the weekschedule is not updated but the day is updated). Is there a way to determine which flow is updated? Or can the first update be ignored when the weekschedule updates?
I found a solution, but it might not be the best one. As flow1.combine(flow2) emits when either flow1 or flow2 emits a value, it is basically an OR function. As I want to emit when either weekSchedule is updated or (not weekschedule and day), and weekschedule is only updated when week is updated which in turn depends on how day is updated. So I introduced an intermediaty flow _changedDaySameWeek which emits a day value if the day changes, but the week stays the same.
For the daySchedule flow I use combine with the changedDaySameWeek flow like this:
which results in the daySchedule updating when either the day is updated and the weekschedule is not, or the weekschedule is updated (and thus changedDaySameWeek is not). So the dayschedule is updated only once on a weekSchedule change and shows no invalid intermediate result.