协程和Flow使用场景

来源:13-9 案例:协程在 Android 中的应用

默小铭

2021-11-25

不好意思,老师可能我描述的不好,老师没有get到我的疑问点

我的疑问不是stateFlow, stateFlow其实直接理解成带默认值的LiveData就好

我的疑问点是:

  1. 一个页面多个网络请求怎么添加 一个"正在加载中…"的转圈圈弹窗
    • 协程写法
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.")
                }
        }
    
  1. 一个网络请求的返回结果,作为下个网络请求的参数

    • 如果只用协程

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)
   		}
}

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

当然是选代码量少的一眼能看懂逻辑的。

0
2
bennyhuo
这才对嘛哈哈
2021-11-26
共2条回复

学会Kotlin 突破开发语言瓶颈

如果有一门语言可以取代Java,那么它一定是Kotlin。

1760 学习 · 481 问题

查看课程