You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android多次绘制Bitmap后滑动SurfaceView触发ANR问题求助

SurfaceView滑动时ANR及刷新残留问题

我在SurfaceView中多次调用canvas.drawBitmap(...)绘制内容,通过自定义GestureDetector的onScroll(...)方法调用surfaceView.setX(gs.moveX); surfaceView.setY(gs.moveY);滑动SurfaceView时,应用出现冻结(ANR)。SurfaceView的绘制由GameThread控制,每次会执行3次canvas.drawBitmap(...)操作。值得注意的是,注释掉drawTmxMaps(...)中的第二或第三次canvas.drawBitmap(...)后,滑动功能基本可用但存在卡顿。

相关代码

Loader.java

private static Map<Integer, Bitmap[]> differentFramesMap = new HashMap<>();
private static Map<Integer, Canvas[]> differentCanvasesMap = new HashMap<>();

(...)

public static void drawTmxMaps(Canvas canvas, Context context) {
    canvas.drawBitmap(differentFramesMap.get(0)[framesFirstAnimIter], 0, 0, PaintTemplates.getInstance(context).pMap);
    canvas.drawBitmap(differentFramesMap.get(1)[framesSecondAnimIter], 0, 0, PaintTemplates.getInstance(context).pMap);
    canvas.drawBitmap(differentFramesMap.get(2)[framesThirdAnimIter], 0, 0, PaintTemplates.getInstance(context).pMap);

    if (!isIterStarted) {
        iterTmxFrames();
        isIterStarted = true;
    }
}

private static void iterTmxFrames() {
    runnable = () -> {
        framesFirstAnimIter++;
        framesSecondAnimIter++;
        framesThirdAnimIter++;
        if (framesFirstAnimIter == 3)
            framesFirstAnimIter = 0;
        if (framesSecondAnimIter == 2)
            framesSecondAnimIter = 0;
        if (framesThirdAnimIter == 2)
            framesThirdAnimIter = 0;
        handler.postDelayed(runnable, 1000);
    };
    handler.postDelayed(runnable, 1000);
}

MyThread.java

@Override
public void run() {
    while (isRunning) {
        startTime = SystemClock.uptimeMillis();
        Canvas canvas = surfaceHolder.lockCanvas(null);
        if (canvas != null) {
            synchronized (surfaceHolder) {

                TmxLoader.drawTmxMaps(canvas, gameSurface.getContext());

                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }

        loopTime = SystemClock.uptimeMillis() - startTime;

        if (loopTime < delay) {
            try {
                Thread.sleep(delay - loopTime);
            } catch (InterruptedException e) {
                Log.e("Interupted ex", e.getMessage());
            }
        }
    }
}

问题更新(已解决部分)

目前已消除ANR,但Surface未正确刷新,屏幕上残留旧绘制位置(表现为滑动后旧内容未被覆盖,留下残影)。
已通过在GameThread的run()方法开头添加canvas.drawARGB(255, 0, 0, 0);解决该刷新问题。

内容的提问来源于stack exchange,提问作者user21172734

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 07:32:53