2

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

我猜这是因为 SurfaceView 中的绘图开始得太早(当然我确保绘图发生在surfaceCreated()and之间surfaceDestroyed()),我绘图线程应该在完全初始化之后开始,也许与 Activity 相关?

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

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

这个SurfaceView作为一个普通的View放在布局文件中,下面是用来在Surface上绘制的代码。

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);
        }

    }
}
4

1 回答 1

1

你不应该在andThread.sleep之间调用,它应该只在画布解锁后调用。SurfaceHolder.lockCanvasSurfaceHolder.unlockCanvasAndPost

In your code example canvas remains locked almost all the time and cause starvation. There is only a little window for SurfaceFlinger to take a canvas a process it. So sometimes this code could fail and that's why ANR errors were sporadic.

于 2012-10-12T14:38:43.153 回答