Android:高效准确地重复绘制许多小形状

Android:高效准确地重复绘制许多小形状,android,android-canvas,android-bitmap,ondraw,Android,Android Canvas,Android Bitmap,Ondraw,我在安卓上做一个项目,它构建了阿贝尔沙堆(一种2D细胞自动机)。我有一个网格的细胞(开始小,但后来增长),我画正方形(或圆圈)在网格上显示每个细胞的状态。在每一步中,我更新的单元格通常不到30% 我的基本方法如下: 我将所有形状绘制到画布并将其缓存为位图,然后在每一步我只更新需要更新的单元格,然后缓存结果并重复。当栅格相当小(小于50 x 50)时,这种方法效果很好,但随着栅格大小的增加,效果越来越不理想。问题是 1) 当更新数量变高时,速度太慢 2) 即使运行平稳,图形看起来也不干净-例如,一

我在安卓上做一个项目,它构建了阿贝尔沙堆(一种2D细胞自动机)。我有一个网格的细胞(开始小,但后来增长),我画正方形(或圆圈)在网格上显示每个细胞的状态。在每一步中,我更新的单元格通常不到30%

我的基本方法如下:

我将所有形状绘制到画布并将其缓存为位图,然后在每一步我只更新需要更新的单元格,然后缓存结果并重复。当栅格相当小(小于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>();
    }
@覆盖
受保护的void onDraw(画布){
super.onDraw(帆布);
如果(准备就绪){
如果(需要完成绘制){
this.cachedBitmap=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
cacheCanvas=新画布(this.cachedBitmap);
doInitialDrawing(cacheCanvas);
drawBitmap(this.cachedBitmap,0,0,null);
needsCompleteDraw=false;
}否则{
drawBitmap(this.cachedBitmap,0,0,null);
doPartialRedraws(cacheCanvas);
}
}
}
private void doInitialDrawing(画布清理){
对于(int i=0;i
我的paint对象将antialias设置为true,我尝试将样式设置为FILL和FILL_以及_STROKE


任何建议都将不胜感激。

好的。这里有几个问题

1) 永远不要在onDraw中创建画布。如果您认为有必要,那么您还没有正确地构建图形代码

2) 绘制缓存位图的目的不是在onDraw中绘制缓存,而是在自己的线程上绘制缓存,或者至少不是在绘制时绘制缓存


应该有第二个线程根据需要绘制缓存的位图,然后在视图上调用postInvalidate()。onDraw函数只能调用drawBitmap,将缓存的位图绘制到屏幕上。

屏幕上的单元格越多,编写游戏的距离就越近(在线搜索各种资源)。或者,您可能想看看其他生活型开源游戏项目如何处理屏幕性能。您也可以参考Android文档(开发-API指南-动画和图形-画布和绘图)使用一个表面视图,你可以使用一个单独的线程,这是非常有效的,我相信它会解决你的问题。