为什么在协程后台线程调用Canvas绘制会出现位置异常问题
协程包裹Canvas绘制出现位置异常的原因
- Canvas生命周期不允许异步操作
系统传入onDraw(canvas: Canvas)的Canvas对象仅在onDraw方法同步执行期间有效。当onDraw方法执行结束后,系统会立即将当前帧的渲染内容提交到渲染管线,对应的Canvas会被回收复用,其内部的裁剪区域、坐标偏移矩阵、绘制上下文状态都会被重置,用于后续其他View或者下一帧的绘制。你使用Dispatchers.Default启动后台协程属于异步操作,等协程内的drawLine执行时,onDraw早已返回,此时操作的Canvas已经不处于当前View的正确绘制状态,自然会出现位置偏移。 - Android绘制操作必须在主线程执行
Android的UI渲染体系不是线程安全的,所有和View绘制相关的操作都要求在主线程执行,在后台线程操作Canvas本身就属于不符合规范的未定义行为,除了位置异常外,还可能出现绘制闪烁、内容错乱、应用崩溃等随机问题。 - 宽高数值正确不代表绘制状态正确
你核对的width和height属于View本身的属性,和Canvas的状态无关,所以数值不会变化。但此时Canvas的坐标原点已经不是当前View的左上角,所以哪怕你传入的坐标值是正确的,最终绘制的位置也会出现偏移。
修复方案
如果存在耗时的绘制计算逻辑,仅将计算部分放到后台协程执行,计算完成后切回主线程调用invalidate()触发重绘,在onDraw中使用计算好的结果同步执行绘制操作即可,不要把绘制操作本身放到异步线程执行。
内容的提问来源于stack exchange,提问作者Elye
相关产品推荐
相关产品推荐

