【发布时间】:2014-03-12 23:27:22
【问题描述】:
我正在开发一个类似于绘画的应用程序,但我在运行它时遇到了一些麻烦。
我知道我在每一帧都重新绘制了所有对象,但这反过来又会在许多对象可见时进一步降低性能。
我还注意到,只清除一次背景,然后在绘画活动时将要绘制的对象添加到表面,会使屏幕闪烁几乎到诱发癫痫的程度。
那么,无论绘制多少对象,让绘图应用 100% 平滑的最佳方法是什么?
癫痫诱发代码:
public void run()
{
while (running)
{
if (!holder.getSurface().isValid())
continue;
if (drawObjectsToAdd.size() == 0)
continue;
drawing = true;
Canvas c = holder.lockCanvas();
if (redrawBackground)
{
c.drawARGB(255, 255, 255, 255);
redrawBackground = false;
}
drawObjects.addAll(drawObjectsToAdd);
drawObjectsToAdd.clear();
for (DrawObject draw : drawObjects)
{
draw.Draw(c, paint);
}
holder.unlockCanvasAndPost(c);
drawing = false;
}
}
一旦将新对象添加到线程之外,它就会添加一个新对象,但它会使屏幕闪烁得如此之多,这让我很头疼——而且我只重绘了一次背景。
一开始很流畅,但一段时间后变得迟钝,可能是由于最后不得不添加数百个对象:
public void run()
{
while (running)
{
if (!holder.getSurface().isValid())
continue;
if (drawObjectsToAdd.size() > 0)
{
drawObjects.addAll(drawObjectsToAdd);
drawObjectsToAdd.clear();
redraw = true;
}
if (clear)
{
drawObjectsToAdd.clear();
drawObjects.clear();
redraw = true;
clear = false;
}
if (!redraw)
continue;
drawing = true;
Canvas c = holder.lockCanvas();
c.drawARGB(255, 255, 255, 255);
for (DrawObject draw : drawObjects)
{
try
{
draw.Draw(c, paint);
}
catch (Exception ex) { }
}
holder.unlockCanvasAndPost(c);
drawing = false;
redraw = false;
}
}
我,至少对于这个应用程序来说,想要存储所有添加的对象,所以它的绘制方式并不重要,只要它一路平滑即可。最好添加一个圆圈 - 它会在表面上渲染一个新的位图,而不必每帧重绘大量对象 - 而是存储它们但不要添加已绘制的对象。
更新
我想要的伪代码:
If no background is drawn
Draw background color
If new items have been added
Draw only new items to the background
Store new items in objects list
这样,我们只会绘制一次背景。添加新项目时,仅将该项目绘制到现有表面。当对象增加时,循环遍历每个项目会大大降低性能,并且使用起来会很不愉快。
更新 2:
private void Draw()
{
while (running)
{
if (!holder.getSurface().isValid())
continue;
if (picture == null)
{
picture = new Picture();
Canvas c = picture.beginRecording(getWidth(), getHeight());
c.drawARGB(255, 255, 255, 255);
picture.endRecording();
}
if (drawObjectsToAdd.size() > 0)
{
drawObjects.addAll(drawObjectsToAdd);
drawObjectsToAdd.clear();
Canvas c = picture.beginRecording(getWidth(), getHeight());
for (DrawObject draw : drawObjects)
{
draw.Draw(c, paint);
}
picture.endRecording();
drawObjects.clear();
}
Canvas c2 = holder.lockCanvas();
c2.drawPicture(picture);
holder.unlockCanvasAndPost(c2);
}
}
Update 2 中的最后一个方法使它在添加圆圈时像“蛇游戏”一样渲染所有线条。看起来像背景上的一条移动的蛇,其中一些圆圈在一帧消失,而其他圆圈则在下一帧消失。如果我跳过重绘每一帧,它会改变哪些圆圈是可见的。
【问题讨论】:
-
我们在谈论多少个对象?
-
需要多少就多少。这是一个绘画应用程序,因此最好在不影响性能的情况下绘画你想要的数量。到目前为止,我唯一的想法是:添加一个对象,从视图中获取位图。添加另一个对象时,重新绘制位图,然后在位图顶部添加新对象。这样,它只会每帧重绘一个位图,而不是数百万个潜在对象。
-
但是修改现有项目,撤消等呢?
-
为什么我存储所有添加的对象,然后当启用该模式时,您只需检查最接近您想要“撤消”或“擦除”点的对象并删除它们。但截至目前,通过我的实现,“SurfaceView.getDrawingCache()”不会返回任何内容。我称之为“SurfaceViewThread 扩展 SurfaceView 实现 Runnable”,也许我做错了。但是我尝试实施的任何其他方法都没有正常工作。
-
但是,是的,这种实现也可能对性能要求很高。但是我现在发现了解决性能问题的方法,因为我的方法有效,但是在添加了很多对象之后它变得很慢。而且我找不到任何关于如何只绘制一次背景,然后只将新添加的对象绘制到表面的信息,而无需重新绘制整个屏幕并添加已添加的每个项目。
标签: android drawing paint surfaceview