我何时应该开始在SurfaceView上绘图?

时间:2012-10-12 08:38:26

标签: android surfaceview

我使用SurfaceView创建选取框功能,但有时在SurfaceView中的绘图线程开始运行后,UI线程被阻止,我的触摸BACK或MENU按钮不会被分派,并且 ANR 生产。这种情况时不时发生。

我想这是因为SurfaceView中的绘图开始太早(当然我确保绘图发生在surfaceCreated()surfaceDestroyed()之间),我猜测< / em>绘图线程应该在完全初始化之后启动,可能与Activity有关吗?

当我在Thread.sleep(100)返回的实际使用Canvas的代码之前添加SurfaceHolder.lockCanvas()以开始绘图时,问题几乎消失了,但它仍然会发生,但是频率很低。如果我在画布上实际绘制某些东西之前让绘图线程睡得足够长,那么问题就再也不会发生了。

看起来我应该在 完全初始化之后开始绘画,但我不知道那是什么。

此SurfaceView用作放置在布局文件中的普通视图,以下是用于在曲面上绘制的代码。

public void run() {
    try {
        // this is extremely crucial, without this line, surfaceView.lockCanvas() may
        // produce ANR from now and then. Looks like the reason is that we can not start
        // drawing on the surface too early
        Thread.sleep(100);
    } catch (Exception e) {}

    while (running) {
        Canvas canvas = null;
        try{

            long ts = System.currentTimeMillis();

            canvas = surfaceHolder.lockCanvas();
            if (canvas != null) {
                synchronized (surfaceHolder) {
                    doDraw(canvas);
                }

                ts = System.currentTimeMillis() - ts;
                if (ts < delayInterval) {
                    Thread.sleep(delayInterval - ts);
                }
            }

        } catch (InterruptedException e) {
            // do nothing
        } finally {
            if (canvas != null)
                surfaceHolder.unlockCanvasAndPost(canvas);
        }

    }
}

1 个答案:

答案 0 :(得分:1)

您不应在Thread.sleepSurfaceHolder.lockCanvas之间调用SurfaceHolder.unlockCanvasAndPost,只有在解锁了画布后才能调用它。

在您的代码示例中,画布几乎始终处于锁定状态并导致starvation。 SurfaceFlinger只有一个小窗口可以将画布作为一个过程。所以有时这段代码可能会失败,这就是为什么ANR错误是零星的。