android 如何使用协程异步处理数据?

wxclj1h5  于 2023-08-01  发布在  Android
关注(0)|答案(4)|浏览(117)

我需要执行4个并行请求。下面是我的代码:

suspend fun fetchAsyncData() = coroutineScope {
    val first = async { repository.taskFirst() }
    val second = async { repository.taskSecond() }
    val third = async { repository.taskThird() }
    val fourth = async { repository.taskFourth() }

    val firstResult = first.await()
    val secondResult = second.await()
    val thirdResult = third.await()
    val fourthResult = fourth.await()
    
}

字符串
问题是,使用这种方法,请求是并行执行的,但我可以同时得到答案。也就是说,如果有些请求将执行45秒,有些将执行3秒,那么我将只能在45秒后处理请求的结果。我的任务是,一旦接收到第一个请求的响应,就将其传递给视图模型,这样它就可以在片段中显示这段数据。此外,一旦接收到对请求的另一个响应,就再传输一个数据,依此类推。
这是怎么做到的,请帮助我。

g0czyy6m

g0czyy6m1#

也许这样的东西可以为你工作:

fun getRepoFlow() = channelFlow {

        coroutineScope {
            launch { send(async { "1" }.await()) }
            launch { send(async { delay(1000L); "2" }.await()) }
            launch { send(async { "3" }.await()) }
        }

    }

字符串

e7arh2l6

e7arh2l62#

如果所有的任务返回相同的结果,那么您可以创建一个流并异步地向其发送数据。下面是一个例子:

fun main() {
    // a flow object inside your viewModel
    val flow: MutableStateFlow<Data?> = MutableStateFlow(null)

    // observe the flow. e.g. For android in Activity's lifecycle
    CoroutineScope(Dispatchers.Unconfined).launch {
        flow.collect {
            println(it)
        }
    }

    // get data from viewModel
    CoroutineScope(Dispatchers.Unconfined).launch {
        launch {
            flow.value = task1()
        }

        launch {
            flow.value = task2()
        }
    }

    // app's lifespan. Not needed in practical applications.
    while (true) {}
}

suspend fun task1(): Data {
    delay(2000)
    return Data(1, Date())
}

suspend fun task2(): Data {
    delay(1000)
    return Data(2, Date())
}

data class Data(val d: Int, val time: Date)

字符串
但是如果tasks返回不同的数据,那么您可以创建多个flow,并在每个任务返回时发送数据。

ar7v8xwq

ar7v8xwq3#

通过这种方法,您可以处理不同类型的响应和失败案例。

sealed class ResponseState {
            data class Content<T>(val data: T) : ResponseState()
            // handle network and server error state
            //data class error(e : Throwable): ResponseState()

        }

        val flow: MutableStateFlow<ResponseState?> = MutableStateFlow(null)
        coroutineScope {
            launch {
                val res = repository.taskFirst() // return type a
                flow.value = ResponseState.Content<a>(res)
            }
            launch {
                val res = repository.taskSecond()// return type b
                flow.value = ResponseState.Content<b>(res)
            }
            launch {
                val res = repository.taskThird() // return type c
                flow.value = ResponseState.Content<c>(res)
            }
            launch {
                val res = repository.taskFourth() // return type d
                flow.value = ResponseState.Content<d>(res)
            }
        }
        // here is an example with flow, you can use live data as well
        CoroutineScope(Dispatchers.Main).launch {
            flow.collect {
                when (it) {
                    is ResponseState.Content<*> -> {
                        // check response type
                        when (it.data) {
                            is a -> {
                                //handle taskFirst response
                            }

                            is b -> {
                                //handle taskSecond response
                            }

                            is c -> {
                                //handle taskThird response
                            }

                            is d -> {
                                //handle taskFourth response
                            }

                            else -> {}
                        }
                    }
                }
            }
        }

字符串

oo7oh9g9

oo7oh9g94#

你应该使用异步后的每一行代码。示例:

suspend fun fetchAsyncData() = coroutineScope { 

val first = async { repository.taskFirst() }
val firstResult = first.await()
//use firstResult here

val second = async { repository.taskSecond() }
val secondResult = second.await()
//use secondResult here

val third = async { repository.taskThird() }
val thirdResult = third.await()
//use thirdResult here

val fourth = async { repository.taskFourth() }
val fourthResult = fourth.await()
//use fourthResult here

}

字符串
调用fetchAsyncData()函数:

lifecycleScope.launch {
        fetchAsyncData()
    }

相关问题