-1

I am creating a text recognition app and I want the flow to emit values only if the result is constant for a given duration. Also if no value is emitted for a certain amount of time, reject the previous value.

General Grievance
  • 4,555
  • 31
  • 31
  • 45

1 Answers1

0

This might work (I didn't test it). It relies on a stream of new values coming in regularly, because it only checks the duration when new values come. If a single value comes in and nothing else for a long time, it won't emit until the subsequent item arrives.

fun <T: Any> Flow<T>.filterToHeldTime(duration: Long): Flow<T> {
    var value: T? = null
    var changeTime = 0L
    return transform { newValue ->
        value?.let {
            if (System.currentTimeMillis() - changeTime >= duration) {
                emit(it)
            }
        }
        if (newValue != value) {
            value = newValue
            changeTime = System.currentTimeMillis()
        }
    }.distinctUntilChanged()
}

If you want to support a nullable type, you'll have to introduce a Boolean to track if the first value was received yet.

Edit: Maybe this would work. It doesn't rely on waiting for the next value before deciding to emit. It eagerly emits the value right away if it has remained constant for the specified duration.

fun <T : Any> Flow<T>.filterToHeldTime(duration: Long): Flow<T> = channelFlow {
    var value: T? = null
    var delayedSendJob: Job? = null
    collect { newValue ->
        if (newValue != value) {
            value = newValue
            delayedSendJob?.cancel()
            delayedSendJob = launch {
                delay(duration)
                send(newValue)
            }
        }
    }
}
Tenfour04
  • 83,111
  • 11
  • 94
  • 154