flatMapLatest{}
展平并丢弃上个未执行完毕的流public inline fun <T, R> Flow<T>.flatMapLatest(@BuilderInference crossinline transform: suspend (value: T) -> Flow<R>): Flow<R> =
transformLatest { emitAll(transform(it)) }
这个扩展函数非常好用,当收到下一个流时,会取消上一次未执行完毕的流。举个在Android中的应用例子:
当通过搜索框输入字符实时搜索时,上一次搜索还没处理完毕前收到了下一次搜索请求,此时就自动会把上一次未处理完毕的搜索请求取消掉。
接下来看个例子:
fun flat() {
GlobalScope.launch {
flowOf(
flow {
println("flow1")
delay(1000)
emit(1)
},
flow {
println("flow2")
delay(2000)
emit(2)
}).flatMapLatest {
flow {
it.collect {
emit("haha".repeat(it))
}
}
}.collect {
println("flat collect: $it")
}
}
}
输出结果如下:
可以看到flow2代码块中休眠了2s而flow1只休眠了1s,所以flow1会执行较快,所以当flow1到达处理时而flow2未执行完毕就会被取消掉,最终的结果也只输出了flow1对应的执行结果。
distinctUntilChanged()
去重处理public fun <T> Flow<T>.distinctUntilChanged(): Flow<T> =
when (this) {
is StateFlow<*> -> this // state flows are always distinct
else -> distinctUntilChangedBy(keySelector = defaultKeySelector, areEquivalent = defaultAreEquivalent)
}
最关键的是调用了distinctUntilChangedBy函数,该方法接受两个参数,用来定义去重的规则,我们也可以自定义去重规则。
fun flat() {
GlobalScope.launch {
flow {
println("flow2")
for (i in 0..10) {
emit(10)
}
}
.distinctUntilChanged()
.collect {
println("flat collect: $it")
}
}
}
输出:
takeWhile{}
是否中止流public fun <T> Flow<T>.takeWhile(predicate: suspend (T) -> Boolean): Flow<T> = flow {
return@flow collectWhile { value ->
if (predicate(value)) {
emit(value)
true
} else {
false
}
}
}
这个方法也非常好用,接受一个返回值为布尔类型的函数类型,其中返回true则继续执行流的执行传递,返回false将直接中止后续流的执行。这里也用一个Android的例子说明使用场景:
加载某个列表数据需要同时从本地数据库和网路进行请求,如果网络请求响应快于本地数据库读取,此时当网络响应的结果收到时,直接中断后续流的执行(本地数据库的)。
fun flat() {
GlobalScope.launch {
flow {
for (i in 0..10) {
emit(i)
}
}
.takeWhile {
it in 0..5
}
.collect {
println("flat collect: $it")
}
}
}
看下执行结果:
可以看到当打印到5时就不再输出了,也就说后续的流被中止了。
take(n)
取前n条数据public fun <T> Flow<T>.take(count: Int): Flow<T> {
return flow {
var consumed = 0
try {
collect { value ->
if (++consumed < count) {
return@collect emit(value)
} else {
return@collect emitAbort(value)
}
}
} catch (e: AbortFlowException) {
e.checkOwnership(owner = this)
}
}
}
这个方法和takeWhile{}有点像,不过就是取前n条数据后就中止流的执行,这个场景也挺常见,就不再举例。使用takeWhilt{}的例子调用take(4)的执行效果如下:
阅读量:1766
点赞量:0
收藏量:0