为什么我的可运行给ANR?

Thu*_*bit 5 android

我正在尝试实现一个,基于本教程从a SurfaceView调用它的onDraw()方法.在我开始运行以下代码后,我的应用程序正在提供ANR.Thread

我尝试过实现Runnable,而不是扩展Thread但它仍然给出了ANR.

据我所知,当ANR发生时,应用程序上没有其他任何东西在运行.(ANR仅在我添加此代码时才开始发生:)

package com.thunderrabbit.run;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class MainThread extends Thread {
    private final String TAG = this.getClass().getSimpleName();

    // desired fps
    private final static int    MAX_FPS = 50;
    // maximum number of frames to be skipped
    private final static int    MAX_FRAME_SKIPS = 5;
    // the frame period
    private final static int    FRAME_PERIOD = 1000 / MAX_FPS;  

    private SurfaceHolder surfaceHolder;
    private PageGLSurfaceView gamePanel;
    private boolean running;    // flag to hold game state
    private Canvas canvas;

    long beginTime;     // the time when the cycle begun
    long timeDiff;      // the time it took for the cycle to execute
    int sleepTime;      // ms to sleep (<0 if we're behind)
    int framesSkipped;  // number of frames being skipped 

    public MainThread(SurfaceHolder surfaceHolder, MySurfaceView gamePanel) {
        super();
        this.surfaceHolder = surfaceHolder;
        this.gamePanel = gamePanel;
    }

    public void setRunning(boolean running) {
        this.running = running;
    }

    @Override
    public void run() {
        sleepTime = 0;
        while(running)
        {
            canvas = null;
            try
            {
                synchronized (surfaceHolder)
                {
                    canvas = surfaceHolder.lockCanvas();
                    beginTime = System.currentTimeMillis();
                                    // resetting the frames skipped
                    framesSkipped = 0;
                    // update game state
                    this.gamePanel.update();
                    // render state to the screen
                    // draws the canvas on the panel
                    this.gamePanel.render(canvas);
                    // calculate how long did the cycle take
                    timeDiff = System.currentTimeMillis() - beginTime;
                    // calculate sleep time
                    sleepTime = (int)(FRAME_PERIOD - timeDiff);

                    if (sleepTime > 0) {
                        // if sleepTime > 0 we're OK
                        try {
                            // send the thread to sleep for a short period
                            // very useful for battery saving
                            Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {}
                    }

                    while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
                        // we need to catch up
                        // update without rendering
                        this.gamePanel.update();
                        // add frame period to check if in next frame
                        sleepTime += FRAME_PERIOD;
                        framesSkipped++;
                    }
                    beginTime = System.currentTimeMillis();
                    gamePanel.onDraw(canvas);
                }
            }
            finally
            {
                if (canvas != null)
                {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
            // update game state
            // render state to the screen
        }
        DebugLog.d(TAG, "Game loop executed ");
    }
}
Run Code Online (Sandbox Code Playgroud)

导致ANR的原因是什么?我应该以一种截然不同的方式实现Runnable或扩展Thread吗?

f20*_*20k 1

gamePanel从您的输入扩展SurfaceView并接收您的输入(通过onTouchEvent())。换句话说,它是您的 UI 线程。当您调用时,gamePanel.onDraw(canvas)它处于阻塞状态(等待硬件绘制canvas),因此您会收到 ANR。

似乎MainThread是渲染线程(看看它如何拥有 )canvas,并且它应该是唯一的渲染线程。您的游戏逻辑应该MainGamePanel完全放在一个单独的线程中。

所以理想情况下我会有三个线程:

  • 一个用于输入(主要活动,大部分时间什么都不做)
  • 一个用于游戏逻辑(一个始终更新的单独线程)
  • 一个用于绘图(拥有画布并且一直在绘图)