安卓SurfaceView导致FPS低问题

5

我在使用SurfaceView时遇到了一些帧率问题。我按照一些教程上的典型操作(所有教程都是一样的),但是我的三星Galaxy S(旧版,i9000)无法达到一个合理的帧率。

下面是我用于循环线程的代码。 FPS初始化为30。

@Override
public void run() {
    long ticksPS = 1000/FPS;
    long startTime;
    long sleepTime;
    //fps checker
    long contms=0;
    long lasttimecheck = System.currentTimeMillis();
    int fps=0;
    while (running) {
        long time =  System.currentTimeMillis();
        if(contms>1000) {
            Log.v("FPS",String.valueOf(fps));
            contms=time-lasttimecheck;
            fps=1;
        }
        else {
            fps++;
            contms+=time-lasttimecheck;
        }
        lasttimecheck = time;

        Canvas c = null;
        startTime =time;
        try {
            c = view.getHolder().lockCanvas();
            synchronized (view.getHolder()) {
                view.onDraw(c);
            }
        } finally {
            if (c != null) {
                view.getHolder().unlockCanvasAndPost(c);
            }
        }
        sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
        try {
            if (sleepTime > 10)
                   sleep(sleepTime);
            else {
                Log.w("LOWFPS",String.valueOf(contms));
                sleep(10);
            }
     } catch (Exception e) {}
    }
}

在SurfaceView中,我使用holder.setFormat(PixelFormat.RGBA_8888)初始化了持有者,但我不知道是否需要对位图进行处理以避免无用的CPU工作(我将位图保存在本地变量中,然后绘制它们)。这个游戏非常简单,应该运行得更快。
帧率相当随机,有时运行平稳,有时则不是,但始终低于30FPS。
有任何想法吗???
使用onDraw()方法解释:
@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(bg, 0, 0, null); //1
    stars.draw(canvas,dx,dy);      //2
    if(playing.on()) reactors.draw_reaccio(canvas,dx,dy); //3
    gotes.draw(canvas,dx,dy);     //4
    reactors.draw(canvas,dx,dy);  //5
    sg.draw(canvas);  //6         
    sr.draw(canvas);  //7
    eraser.draw(canvas);  //8
    playing.draw(canvas); //9
    opcions.draw(canvas); //10
}

1) 绘制背景 (480x800) 2) 这是一个包含基本对象(星星)“getHeight()”列表的类,其坐标(x、y)和关联图像的ID(约有9个不同的星星图像) 3) 它为每个相关对象绘制n * 2个圆形,一个填充,另一个描边(大约20个左右) 4) 它绘制游戏的主要对象,小滴水动画。有9种不同类型的滴落物,并且每种滴落物都有5个相关图像的动画(我应该把这5个图像放在一起吗?) 5) 没有动画的与滴落物相同 6到10) 不相关,它只是绘制一幅图像

我想缓慢是由于:(2)由于星星的数量,(4)由于动画,它会在2-3帧之间更改为不同的图像,也许对于内存来说太多了,我想将所有图像合并成只有1个。

在S. Galaxy S i9000上帧速率约为20-22 FPS。


我在我的全新Galaxy Nexus上遇到了类似的问题。我的应用程序大量使用SurfaceView,在其他所有设备上都正常工作。在ICS上,即使在设置中强制启用硬件加速,它也无法使用。 - Kleptine
你能发布绘图代码本身吗?为了确定应用程序中耗时/ CPU 密集的部分,请使用 TraceView:http://developer.android.com/guide/developing/debugging/debugging-tracing.html - molnarm
请发布整个类,否则没有人能够明智地分析您的代码流程。 - poitroae
事实证明,我实际上有一个不同的问题。如果位图经常更改,则启用硬件加速(在ICS上默认情况下)的SurfaceView会变慢。 - Kleptine
2个回答

3
如果禁用绘制,您能获得多少fps?只是为了检查显示管道占用了多少资源。
我尝试了以下操作: 创建5个大小为720 x 480的位图:像素格式为RGB565 从类似于您的循环中将它们显示在SurfaceView上。 唯一的区别是我已经“准备好位图”,而不是在循环中绘制它们。 在Nexus-S手机上实现了以下效果:
FPS:55(我尝试以最快的速度运行循环,没有调节) CPU负载:85%
这就是我决定从JNI渲染我的SurfaceView的原因!!
进行类似的实验,看看您的设备能够在“没有”绘制操作的情况下限制多少资源。如果看起来很好,那么您可以分析是否可以将绘制操作放入预算中。

实际上,我最终遇到了一个不同的问题,但是我会授予您赏金,因为这可能是解决原始帖子问题的最佳方法。 - Kleptine

0

需要考虑的事项:您的绘制例程需要多长时间?

如果在30FPS以下执行有问题,建议不要让它休眠。这并不是一个精确的事情,根据API可能会休眠更少或更多,因此建议暂时将其移除,并让其尽可能快地运行。

我同意上面的评论,请发布绘画代码或注释掉调用绘画例程,并查看您的FPS。

从采样的角度来看,通常只测量1秒钟的话,您可能会观察到值的抖动。

许多绘图后端只能在60的偶数除数中工作。所以如果您正在进行很多操作,可能会多调用一两次,从而使帧速率从60/1 = 60 fps降至60/2 = 30 fps。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接