协程和Flow使用场景
来源:13-9 案例:协程在 Android 中的应用

默小铭
2021-11-25
不好意思,老师可能我描述的不好,老师没有get到我的疑问点
我的疑问不是stateFlow, stateFlow其实直接理解成带默认值的LiveData就好
我的疑问点是:
- 一个页面多个网络请求怎么添加 一个"正在加载中…"的转圈圈弹窗
- 协程写法
suspend fun one(): Int {
delay(1000)
return 1
}
suspend fun two(int: Int): Int {
delay(2000)
return 2 + int
}
fun main(){
GlobalScope.launch {
// 是不是在这里显示弹窗
val sum = withContext(Dispatchers.IO) {
val one = async { one() }
val two = async { two() }
one.await() + two.await()
}
// 判断 将挂起函数阻塞执行,待执行完后隐藏弹窗
}
}
-
Flow 写法 (把多个Flow用 flattenConcat 拼接起来,然后在onStart() 和 onCompletion() 显示或隐藏)
fun flattenConcat() = viewModelScope.launch { flow { //模拟网络请求一 delay(1000) emit(5) }.onStart { //显示弹窗 }.map { flow { //模拟网络请求二 delay(2000) emit("$it") } }.flattenConcat() .onCompletion { //隐藏弹窗 } .collect { Log.i(TAG, "flattenConcat() --> $it.") } }
-
一个网络请求的返回结果,作为下个网络请求的参数
- 如果只用协程
suspend fun one(): Int {
delay(1000)
return 1
}
suspend fun two(int: Int): Int {
delay(2000)
return 2 + int
}
fun main(){
GlobalScope.launch {
val one = one()
val two = two(one)
}
}
-
如果用Flow,可以用map + flattenConcat 实现类似RxJava链式实现
https://www.imooc.com/article/302590 看到老师的这篇手记,有新的理解
fun flattenConcat() = viewModelScope.launch {
flow {
//模拟请求一
delay(1000)
emit(5)
}.map {
flow {
//模拟请求二
delay(1000)
emit("$it")
}
}.flattenConcat()
.collect {
Log.i(TAG, "flattenConcat() --> $it.")
}
}
-
自己还瞎写了一种写法,能跑通,但感觉说不出的奇怪,希望老师给点建议
/** * Flow 嵌套 (应该不建议这么搞) */ fun flowNested() = viewModelScope.launch { flow { emit(1000) }.collect { flow { emit("第一个Flow 发射的值 $it") }.collect { Log.i(TAG, "第二个Flow 发射的值--> $it") } } }
希望老师解答的几个疑问:
上面那两种场景对应的写法有没有什么问题?,特别是最后 Flow直接嵌套Flow,虽然都能处理上面说的场景
如果说没问题,请问下老师是不是这两个多任务的场景,建议优先用协程处理就好,
然后让 Flow 只关注数据流相关的问题,比方说背压,数据转换,课程案例下载文件涉及到多种状态等一些仅靠协程处理不了的问题
写回答
1回答
-
bennyhuo
2021-11-26
当然是选代码量少的一眼能看懂逻辑的。
022021-11-26
相似问题