android - 为什么在 SDK 30 及之后,运行 holder.lockCanvas 和 holder.unlockCanvasAndPost 的后台线程仍然会锁定 UI 线程?
问题描述
我有一个简单的 SurfaceView,它使用 Coroutine Dispatcher.Default 范围在后台运行,代码如下
override fun surfaceCreated(holder: SurfaceHolder) {
doAnimate = true
job = CoroutineScope(Dispatchers.Default).launch {
while (doAnimate && isAttachedToWindow) {
synchronized(holder) {
val canvas = holder.lockCanvas()
Thread.sleep(500)
canvas?.let {
drawAnimate.draw(it)
holder.unlockCanvasAndPost(it)
}
}
}
}
}
此代码在 Android SDK 29 及更早版本中运行良好。我仍然可以上下滚动而不会被Sleep
如下所示的阻止。
您可以从这里获取实际的应用程序和代码
从 Android SDK 30 及更高版本开始,绘图仍然有效。但似乎Sleep
现在阻塞了 Main.UI 线程,我不能再平滑滚动,即使它Sleep
位于协程 Dispatcher.Default 范围(工作线程)后面。
sleep
我意识到我可以通过移动外部holder.lockCanvas()
和holder.unlockCanvasAndPost(it)
范围来解决它。
override fun surfaceCreated(holder: SurfaceHolder) {
doAnimate = true
job = CoroutineScope(Dispatchers.Default).launch {
while (doAnimate && isAttachedToWindow) {
synchronized(holder) {
val canvas = holder.lockCanvas()
canvas?.let {
drawAnimate.draw(it)
holder.unlockCanvasAndPost(it)
}
Thread.sleep(500) // <-- Move here
}
}
}
}
Android SDK 30 及更高版本中发生了哪些变化导致了新行为?这是 Android SDK 30 及更高版本中的错误还是新限制?
确实感觉lockCanvas
andunlockCanvasAndPost
范围现在正在阻塞 UI 线程。真的吗?
解决方案
推荐阅读
- spss - 使用SPSS可以查到人们的习惯是否发生了变化
- reactjs - 如何使用带有 React.js 的预签名 URL 将文件上传到 S3
- reactjs - 在 react-redux 连接组件中进行单元测试时出错
- javascript - 如何在 Firebase 中推送多个项目?
- angular - DatePipe.transform 显示“dd-MM-yyyy”的 InvalidPipeArgument
- r - RStudio 环境 data.frame 行数
- elmish - 等同于 Elm 风格的 model-view-update 中的数据绑定模型更新
- windows - 在 unicode 环境中使用 sed 或类似命令进行多搜索和替换
- python - 计算一个索引中每个字段的所有出现次数
- sql - 名字字段不得包含 3 个具有相同值的连续字符