kir*_*403 5 kotlin kotlin-coroutines
使用 kotlin 协程的最新稳定版本,我试图使用它来实现我的应用程序的功能之一。但是,我有点困惑。
基本上,我有一个函数可以对项目列表做一些工作。这需要大约 700-1000 毫秒。
fun processList(list : ArrayList<String>) : ArrayList<Info> {
val result = mutableListOf<Info>()
for (item in list) {
// Process list item
// Each list item takes about ~ 15-20ms
result.add(info) // add processed info to result
}
return result // return result
}
Run Code Online (Sandbox Code Playgroud)
现在,我想在不阻塞主线程的情况下使用它。所以我在启动块内启动这个函数,这样它就不会阻塞主线程。
coroutineScope.launch(Dispatchers.Main) {
val result = processList(list)
}
Run Code Online (Sandbox Code Playgroud)
这很好用。
但是,我试图将该函数设为挂起函数,以确保它永远不会阻塞主线程。实际上,在函数内部没有任何其他协程启动。还尝试在单独的协程中处理每个列表项,然后将它们全部加入以使其实际使用子协程。但是循环内的那个块使用同步方法调用。所以没有必要让它异步 - 并行。所以我最终有一个像这样的挂起功能:
suspend fun processList(list : ArrayList<String>) : ArrayList<Info> = coroutineScope {
val result = mutableListOf<Info>()
for (item in list) {
// Process list item
// Each list item takes about ~ 15-20ms
result.add(info) // add processed info to result
}
return result // return result
}
Run Code Online (Sandbox Code Playgroud)
开头只有一个挂起修饰符,方法块用coroutineScope { }.
这还重要吗?哪一个更好?如果函数使用协程或长时间运行的函数也应该标记为挂起函数,我应该只使函数挂起吗?
我糊涂了。我已经观看了最近关于协程的所有讨论,但无法清楚地说明这一点。
任何人都可以帮助我理解这一点吗?
更新:
所以我最终有一个这样的功能。只是为了确保永远不会在主线程上调用该函数。并且调用函数不必到处记住这需要在后台线程上调用。通过这种方式,我可以将调用函数的事物抽象化:只要按照指示去做,我不在乎您想在哪里处理这些事物。只需处理并给我结果。因此,它自己的函数负责它需要运行的位置,而不是调用函数。
suspend fun processList(list : ArrayList<String>) : ArrayList<Info> = coroutineScope {
val result = mutableListOf<Info>()
launch(Dispatchers.Default) {
for (item in list) {
// Process list item
// Each list item takes about ~ 15-20ms
result.add(info) // add processed info to result
}
}.join() // wait for the task to complete on the background thread
return result // return result
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?
您希望将 CPU 密集型计算卸载到后台线程,这样 GUI 线程就不会被阻塞。您不必声明任何挂起函数即可实现此目的。这就是您所需要的:
myActivity.launch {
val processedList = withContext(Default) { processList(list) }
... use processedList, you're on the GUI thread here ...
}
Run Code Online (Sandbox Code Playgroud)
以上假设您已将CoroutineScope接口正确添加到您的活动中,如其文档中所述。
更好的做法是推入withContext的定义processList,这样您就不会犯在主线程上运行它的错误。声明如下:
suspend fun processList(list: List<String>): List<Info> = withContext(Default) {
list.map { it.toInfo() }
}
Run Code Online (Sandbox Code Playgroud)
这假设您已将字符串到信息逻辑放入
fun String.toInfo(): Info = // whatever it takes
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2675 次 |
| 最近记录: |