Stylianos Gakis
01/07/2022, 12:23 PMsealed interface Types {
object One : Types
object Two : Types
}
val someFlow: Flow<Types>
someFlow
.filterIsInstance<Types.One>()
.distinctUntilChanged()
.collectLatest() { one ->
// I want this to be cancelled on an emission of `Two` from `someFlow` but keep on going alive without interruption on a repeat emission of `One` if it was `One` before too
coroutineScope {
while(isActive) {
doWork(one)
}
}
}
.map { it as? Types.One }
.distinctUntilChanged()
.collectLatest { one: Types.One? ->
if (one == null) return@collectLatest
//rest of loop code
}
And it seems to be working fine.
But the annoying part is that I need to manually exit it with the if check in the first line, I guess this is unavoidable right?
And overall I just feel like this could be done a bit nicer without the null castings etc. I would love to hear if someone has a better idea 🤔expensivebelly
01/07/2022, 2:12 PMStylianos Gakis
01/07/2022, 2:23 PMMediaPlayer
inside of it, but also keeps track of an internal State with the options Playing, Paused, End
etc. In order to then make sure my UI shows how far in the video we currently are, since I don’t think the Android MediaPlayer
has a callback to report how far in the video it is, I am this coroutine to every X milliseconds get the current progress %
@FloatRange(from = 0.0, to = 1.0)
private fun MediaPlayer.getProgressPercentage(): Float {
return (currentPosition.toFloat() / duration.toFloat()).coerceIn(0f, 1f)
}
to then in turn update the Playing state that also contains a progress Float inside of it.
And I want to start this coroutine when the state turns to Playing
and let it report back really fast, but then stop it when we’re not on Playing
anymore.
Here is the source codeexpensivebelly
01/07/2022, 2:30 PMfun <T : Any> Flow<T>.valve(valveSource: Flow<Boolean>): Flow<T> =
this.combine(valveSource.distinctUntilChanged()) { value: T, valve: Boolean -> value to valve }
.mapNotNull { (value, valve) -> value.takeIf { valve } }
Stylianos Gakis
01/07/2022, 2:38 PMexpensivebelly
01/07/2022, 4:58 PMsomeFlow.distinctUntilChanged()
.flatMapLatest { types ->
if (types is Types.One) {
flow {
while (true) {
emit(doWork(types))
}
}
} else emptyFlow()
}
valve
does not apply to your specific problem, but the code snippet above it shouldStylianos Gakis
01/10/2022, 8:51 AMaudioPlayerState
.map { type -> type.shouldContinuouslyDoWork } // added this as a property to Types to make this easier
.distinctUntilChanged()
.collectLatest { shouldContinuouslyDoWork: Boolean ->
if (shouldContinuouslyUpdateProgress) {
coroutineScope {
while (isActive) {
delay(///)
doWork()
}
}
} else {
doWork()
}
}
Since I am doing the work in-line there and don’t need to transform this to another flow to be used somewhere there was no need for the flatMapLatest that you suggested. But if I did, that looks like a great approach yeah. Thanks a lot for trying to help me out btw!expensivebelly
01/10/2022, 9:46 AMStylianos Gakis
01/10/2022, 10:08 AM