我正在开发一个Android项目,用于构建Abelian Sandpiles(一种2D元胞自动机)。我有一个单元格网格(从小开始但后来长大)我在网格上绘制正方形(或圆圈)以显示每个单元格的状态。在每一步,我通常更新不到30%的细胞。
我的基本方法来自这篇文章:Android: How to get a custom view to redraw partially?
我将所有形状绘制到画布并将其作为位图缓存,然后在每一步我只更新需要更新的单元格,然后缓存结果并重复。当网格相当小(小于50 x 50)时,这种方法效果很好,但随着网格尺寸的增加,网格变得越来越不令人满意。问题在于
1)当更新次数变高时,它太慢了
2)即使它运行平稳,绘图看起来也不干净 - 例如,一行小矩形看起来很不稳定且不一致(见图)。
我确信必须有更好的方法来解决这个问题。使用更大的网格(例如,150 x 150),我绘制宽度为~2.33的圆形或圆形,这不是最佳的。有关提高性能和/或图像质量的建议吗? 简化的绘图代码如下:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (ready) {
if (needsCompleteRedraw) {
this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
cacheCanvas = new Canvas(this.cachedBitmap);
doInitialDrawing(cacheCanvas);
canvas.drawBitmap(this.cachedBitmap, 0, 0, null);
needsCompleteRedraw = false;
} else {
canvas.drawBitmap(this.cachedBitmap, 0, 0, null);
doPartialRedraws(cacheCanvas);
}
}
}
private void doInitialDrawing(Canvas clean) {
for (int i = 0; i < pile.gridHeight; i++) {
for (int j = 0; j < pile.gridWidth; j++) {
int state = pile.getGridValueAtPoint(new Point(j, i ));
clean.drawRect(j * cellSize, i * cellSize, (j + 1 )* cellSize, (i + 1) * cellSize, paints[state]);
}
}
}
private void doPartialRedraws(Canvas cached) {
for (Point p : pile.needsUpdateSet) {
int state = pile.getGridValueAtPoint(p);
cached.drawRect(p.x * cellSize, p.y * cellSize, (p.x + 1 )* cellSize, (p.y + 1) * cellSize, paints[state]);
}
pile.needsUpdateSet = new HashSet<Point>();
}
我的paint对象设置为antialias为true,我尝试将样式设置为FILL和FILL_AND_STROKE。
我们非常感谢任何建议。
答案 0 :(得分:0)
确定。这里有几个问题。
1)不要在onDraw中创建画布。如果您认为需要,则无法正确构建绘图代码。
2)绘制缓存位图的要点不是在onDraw中绘制缓存,而是在自己的线程上绘制 - 或者至少在绘制时不这样做。
您应该有第二个线程根据需要绘制到缓存的位图,然后在视图上调用postInvalidate()。 onDraw函数应该只是对drawBitmap的调用,将缓存的位图绘制到屏幕上。