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

时间:2018-03-18 13:59:40

标签: android kotlin kotlinx.coroutines

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

我也在使用coroutines来等待第一次onDraw调用,使用postOnAnimate()恢复动画循环等等。在这些情况下,UI上下文不能满足我的需要,因为它通过向事件循环提交项来异步恢复延续,即使在UI线程上调用了cont.resume()

在等待onDraw上的第一次ImageView调用的情况下,这种情况变得特别糟糕:我必须根据现在已知的视图维度重新定位图像。然而,由于协同程序异步恢复,onDraw()完成,然后再运行几次,然后我的协程才恢复。用户会出现闪烁,因为短暂出现的图像位置不正确。

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

1 个答案:

答案 0 :(得分:1)

是。您可以在Adroind上下文here中学习awaitFrame的实现,并使用类似的技巧。特别是,当使用suspendCancellableCoroutine函数挂起协同程序时,如果您已通过resumeUndispatched函数在此调度程序的上下文中运行,则可以要求恢复它 undispatched CancellableContinuation。您必须提供对相应调度程序的引用作为“证明”,并使用以下代码模式:

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

这种方法在某种意义上是安全的,如果您正在恢复的协程使用不同的调度程序,那么它仍将被分派给适当的调度程序。仅当调度在您指定的调度程序中运行时,才会禁止调度。