Android 如何使UI调度程序立即恢复继续

Android 如何使UI调度程序立即恢复继续,android,kotlin,kotlinx.coroutines,Android,Kotlin,Kotlinx.coroutines,我一直在我的Android项目中大量使用协同程序。例如,我使用它们将阻塞调用和CPU密集型任务移交给线程池。这就是launch(UI)完美工作的地方:它确保在UI线程上继续 我还使用协同程序来处理诸如等待第一个onDraw调用、使用postOnAnimate()恢复动画循环等。在这些情况下,UI上下文无法满足我的需要,因为它通过向事件循环提交一个项来异步恢复继续,即使cont.resume()在UI线程上调用 在等待ImageView的第一次onDraw调用的情况下,这变得尤其糟糕:我必须根据现

我一直在我的Android项目中大量使用协同程序。例如,我使用它们将阻塞调用和CPU密集型任务移交给线程池。这就是
launch(UI)
完美工作的地方:它确保在UI线程上继续

我还使用协同程序来处理诸如等待第一个
onDraw
调用、使用
postOnAnimate()
恢复动画循环等。在这些情况下,UI上下文无法满足我的需要,因为它通过向事件循环提交一个项来异步恢复继续,即使
cont.resume()在UI线程上调用

在等待
ImageView
的第一次
onDraw
调用的情况下,这变得尤其糟糕:我必须根据现在已知的视图尺寸重新定位图像。但是,由于协同路由是异步恢复的,
onDraw()
完成,然后再运行几次,然后我的协同路由才会恢复。由于位置不正确的图像短暂出现,用户体验到闪烁


在UI线程上调用
cont.resume()
时,是否有强制UI调度程序立即恢复的选项?

是。您可以在特定上下文中研究
waitframe
的实现,并使用类似的技术。特别是,当使用
suspendCancelableCorroutine
函数挂起协同路由时,如果您已经在该调度程序的上下文中运行,则可以在生成的
CancelableContinuation
中使用
resumeUndispatched
函数,请求将其恢复为未调度。您必须提供对相应调度器的引用作为“证明”,并使用以下代码模式:

with(continuation) { dispatcher.resumeUndispatched(value) }

这种方法是安全的,因为如果您正在恢复的协同路由使用的是不同的调度程序,那么它仍然会被调度到相应的调度程序。只有在您指定的调度程序中运行调度时,才会抑制调度。

waitframe
正是我研究的代码,但我被
resumendispatched
上的文档甩了:“此功能设计为仅由CoroutineDispatcher实现本身使用。不应在通用规范中使用。”(原始强调).是否被视为私有/不稳定API?其想法是,只有dispatcher实现需要使用它,但Android似乎打开了一个蠕虫罐,在那里可能有很多有用的点。我想知道是否有不同的解决方案来解决这个问题。我们在
启动
何处遇到了类似的问题例如,在
onClick
事件侦听器中,您可能希望
启动一个新的UI协同程序,但没有必要通过dispatcher进行调度,因此添加了
CoroutineStart.UNDISPATCHED
。是的,这从另一端解决了相同的问题。在我的项目中,我实际上定义了一个
启动
函数,该函数可以ODE
launch(UI,start=UNDISPATCHED)
。默认情况下,
resumeUndispatched
行为的缺点是什么?如果您启动undispatched,那么外部代码将不会运行,直到您启动的代码挂起。如果UI上下文是多线程的,并且假定您没有任何长时间运行的代码,则可能没有问题,但因为我们的默认上下文是mulTithread它没有太多的恢复未转储的意义。此外,您使用更多的操作系统堆栈未转储,可能最终导致堆栈溢出。被调度只是一个更安全的默认值。请阅读以下内容:如果您对更好的语法有想法,可以服务于您的用例,请在