我在自定义视图中覆盖了onDraw()方法。我的方法如下:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
data.lockData(); // uses reentrantlock
Bitmap bm = data.getBitmap();
if (bm != null) {
canvas.drawBitmap(bm,0,0,mPaint);
}
data.unlockData();
}
还有另一个线程更新位图,该线程还使用lockData()方法来确保对位图的序列化访问。但是,我看到正在绘制的位图包含不完整的更新,即它正在被另一个线程更新的过程中被绘制到屏幕上。我不知道Android绘图管道的细节有足够的细节(或实际上有任何细节:),但我认为这是由于drawBitmap()实际上并没有绘制位图,而只是将它放入绘制操作队列使用指向位图的指针,稍后系统的另一部分将使用此指针将位图像素的所需部分复制到将在屏幕上显示的缓冲区。因此,实际绘图不受互斥锁的保护。
有一种经典的解决方案,即双缓冲,我认为可以在这种情况下起作用。但是,我仍然认为我的绘制线程可能如此之快,以至于它实际上更新了在实际绘制完成之前再次绘制的缓冲区。此外,我的位图可能非常大,分配一个单独的缓冲区会有点浪费。
我的问题是:
我上面说明了不完整绘制的原因是否正确,即drawBitmap在位图数据实际复制到显示之前返回?您能否提供有关绘图如何运作的详细信息的参考资料?
有没有办法知道实际绘制位图的时间,因此修改位图也是安全的?
如果双缓冲是唯一的解决方案,在允许使用新数据再次更新buffer1之前,如何确保buffer1已完成绘图?
答案 0 :(得分:1)
我无法使View绘图同步。它工作的一种方法是从onDraw()方法中进行计算,即Bitmap bm = data.getBitmap();会计算更新的位图。这样做的缺点是,这将在计算期间阻止UI线程,从而导致错误的输入事件等示例。
可以克服的一种方法是使用SurfaceView。可以在单独的线程中进行计算和绘制,从而序列化两个操作,同时仍然保持UI线程空闲。
答案 1 :(得分:0)
将 image.setDrawingCacheEnabled(真);
做得好吗?将此设置为true可以从新绘制的画布中拉出位图。似乎会与实际绘图同步,以便随后执行:
imageBitmap = image.getDrawingCache();
你会得到一张完全绘制的图像