英文:
Sample Flow with last item
问题
Sample from Kotlin Coroutine: 来自Kotlin Coroutine的示例 https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/sample.html
Doesn't emit the last element if the parent flow is finished before the time frame.:如果父流在时间窗口之前完成,则不会发出最后一个元素。
From Docs: 来自文档:
Note that the latest element is not emitted if it does not fit into the sampling window.:请注意,如果最新元素不适合抽样窗口,则不会发出。
I want an operator that acts just as the sample but emits the last value when the timeframe reaches.:我想要一个操作符,与抽样相同,但在时间窗口到达时发出最后一个值。
The last value is important in my case.:在我的情况下,最后一个值很重要。
Eg code: 例如代码:
val k = (0..100).asFlow().onEach {
    delay(200)
}
val k2 = k.sample(500)
k2.collectLatest {
    println(it)
}
A custom operator would do if none is provided by the library.:如果库中没有提供操作符,可以使用自定义操作符。
英文:
Sample from Kotlin Coroutine https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/sample.html
Doesn't emit the last element if the parent flow is finished before the time frame.
From Docs:
Note that the latest element is not emitted if it does not fit into the sampling window.
I want an operator that acts just as the sample but emits the last value when the timeframe reaches.
The last value is important in my case.
Eg code:
val k = (0..100).asFlow().onEach {
        delay(200)
    }
    val k2 = k.sample(500)
    k2.collectLatest {
        println(it)
    }
A custom operator would do if none is provided by the library.
答案1
得分: 1
你可以尝试这个。这段代码应该是不言自明的。我没有严格测试过它!
fun <T> Flow<T>.sampleAndKeepLast(periodMillis: Long): Flow<T> {
    require(periodMillis > 0) { "Sample period should be positive" }
    return channelFlow {
        var isDone = false
        val empty = Any()
        var lastValue: Any? = empty
        onEach { lastValue = it }
            .onCompletion { isDone = true }
            .launchIn(this)
        while (!isDone) {
            delay(periodMillis)
            if (lastValue !== empty) {
                @Suppress("UNCHECKED_CAST")
                send(lastValue as T)
                lastValue = empty
            }
        }
        if (lastValue !== empty) {
            @Suppress("UNCHECKED_CAST")
            send(lastValue as T)
        }
    }
}
英文:
You can try this. The code should be self-explanatory. I did not rigorously test it!
fun <T> Flow<T>.sampleAndKeepLast(periodMillis: Long): Flow<T> {
    require(periodMillis > 0) { "Sample period should be positive" }
    return channelFlow {
        var isDone = false
        val empty = Any()
        var lastValue: Any? = empty
        onEach { lastValue = it }
            .onCompletion { isDone = true }
            .launchIn(this)
        while (!isDone) {
            delay(periodMillis)
            if (lastValue !== empty) {
                @Suppress("UNCHECKED_CAST")
                send(lastValue as T)
                lastValue = empty
            }
        }
        if (lastValue !== empty) {
            @Suppress("UNCHECKED_CAST")
            send(lastValue as T)
        }
    }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论