我使用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);
}
}
}
答案 0 :(得分:1)
您不应在Thread.sleep
和SurfaceHolder.lockCanvas
之间调用SurfaceHolder.unlockCanvasAndPost
,只有在解锁了画布后才能调用它。
在您的代码示例中,画布几乎始终处于锁定状态并导致starvation。 SurfaceFlinger只有一个小窗口可以将画布作为一个过程。所以有时这段代码可能会失败,这就是为什么ANR错误是零星的。