【2025最新版Kotlin教程】Kotlin第一行代码系列第二十课-协程Flow
Flow 极其强大,可以说用的好Flow才算真正掌握协程。
它比Channel用的场景多,因为它传输数据过程中可以改变。
使用场景:复杂的异步场景,我们就可以使用 Flow
中间操作符:可以说集合有的,它都有
简单示例代码:
fun main() {
// 方式1:flow 用emit发送数据
runBlocking {
flow{
emit(1)
emit(2)
emit(3)
emit(4)
emit(5)
}.filter { it > 2 }
.take(2)
.collect {
println(it)
}
}
// 方式2:flowOf()
runBlocking {
flowOf(1, 2, 3, 4, 5)
.filter { it > 2 }
.map { it * 2 }
.take(2)
.collect {
println(it)
}
}
// 方式3:asFlow()
runBlocking {
listOf(1, 2, 3, 4, 5)
.asFlow()
.filter { it > 2 }
.map { it * 2 }
.take(2)
.collect {
println(it)
}
}
/**
* 注意:中间操作符,有顺序的
* 下面代码就什么也没接收到
*/
runBlocking {
flowOf(1, 2, 3, 4, 5)
.take(2)
.filter { it > 2 }
.map { it * 2 }
.collect {
println(it)
}
}
/**
* onStart,onnCompletion,异常捕获就不说了
*/
//===================================== flow的线程切换 =============================================================
// 关键字 flowOn ,影响到它之前的操作符
runBlocking {
flowOf(11, 22, 33, 44, 55)
.filter {
println("Coroutine in filter:${Thread.currentThread().name}")
it > 2
}
.flowOn(Dispatchers.IO)
.take(2)
.map {
println("Coroutine in Map:${Thread.currentThread().name}")
it * 2
}
.collect {
println("Coroutine in collect:${Thread.currentThread().name}")
println(it)
}
}
// 关键字 launchIn
// 代表整个flow在那线程运行,如果你要某处上游在那线程运行在独自调flowOn
val mySingleDispatcher = Executors.newSingleThreadExecutor {
Thread(it, "MySingleThread").apply { isDaemon = true }
}.asCoroutineDispatcher()
val scope = CoroutineScope(mySingleDispatcher)
runBlocking {
flow{
emit(1111)
emit(2222)
emit(3333)
emit(4444)
emit(5555)
}
.filter {
println("Coroutine in filter 1111:${Thread.currentThread().name}")
it > 2
}
.flowOn(Dispatchers.IO)
.take(2)
.map {
println("Coroutine in map 1111 :${Thread.currentThread().name}")
it * 2
}
.flowOn(Dispatchers.Default)
.onEach {
println("Coroutine in each 1111:${Thread.currentThread().name}")
println(it)
}
.launchIn(scope)
}
// 如果我想collect里面切换线程呢,用withContext{}
/**
* 注意flow里面就不提倡用用withContext了
*/
runBlocking {
flowOf(111, 222, 333, 444, 555)
.filter {
it > 2
}
.flowOn(Dispatchers.IO)
.take(2)
.map {
it * 2
}
.collect {
withContext(Dispatchers.IO){
println("Coroutine in collect:${Thread.currentThread().name}")
println(it)
}
}
}
// ============================================ flow终止符 ======================================================
// 终止符有 first()、single()、fold{}、reduce{},toList()
// =============================================== flow是冷和懒的 ==============================================
/**
* 表现在没有终止符,我是不发送的
* 我是一条条数据发送的
*/
}
整个kotlin教程的源码项目结构图:
\