![](/img/trans.png)
[英]In Kotlin, how do I convert “CompletableFuture<Optional<T>>” to “Flow<T?>”?
[英]How do I modify Kotlin Flow distinctUntilChanged to add an expiry time
我如何使用distinctUntilChanged()
並向其添加到期時間,這意味着如果流中存在相同的值,我們仍會收集它,因為它比發出前一個重復值后的expiry
毫秒數長。
flow {
emit("A") // printed
emit("B") // printed
emit("A") // printed
emit("A") // NOT printed because duplicate
delay(5000)
emit("A") // printed because 5 seconds elapsed which is more than expiry
}
.distinctUntilChanged(expiry = 2000)
.collect {
println(it)
}
我想這樣打印:
A
B
A
A
這是測試它的代碼:
@Test
fun `distinctUntilChanged works as expected`(): Unit = runBlocking {
flow {
emit("A") // printed
emit("B") // printed
emit("A") // printed
emit("A") // NOT printed because duplicate
delay(5000)
emit("A") // printed because 5 seconds elapsed which is more than expiry
}
.distinctUntilChanged(expiry = 2000)
.toList().also {
assertEquals("A", it[0])
assertEquals("B", it[1])
assertEquals("A", it[2])
assertEquals("A", it[3])
}
}
我認為這會起作用,但我沒有進行太多測試。 我認為邏輯是不言自明的。 havePreviousValue
存在的原因是萬一T
可以為空並且第一個發出的值是null
。
fun <T> Flow<T>.distinctUntilChanged(expiry: Long) = flow {
var havePreviousValue = false
var previousValue: T? = null
var previousTime: Long = 0
collect {
if (!havePreviousValue || previousValue != it || previousTime + expiry < System.currentTimeMillis()) {
emit(it)
havePreviousValue = true
previousValue = it
previousTime = System.currentTimeMillis()
}
}
}
另外一個選擇:
fun <T> Flow<T>.distinctUntilChanged(expiry: Long) =
merge(
distinctUntilChanged(),
channelFlow {
val shared = buffer(Channel.CONFLATED).produceIn(this)
debounce(expiry).takeWhile { !shared.isClosedForReceive }.collect {
val lastVal = shared.receive()
shared.receive().let { if(lastVal == it) send(it) }
}
}
)
它基本上將非獨特值添加回 distinctUntilChanged()。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.