【问题标题】:Drawing to Canvas in Android throws Null Pointer Exception在 Android 中绘制到 Canvas 会引发空指针异常
【发布时间】:2014-02-25 08:20:22
【问题描述】:

我正在尝试创建一个简单的背景渲染,顶部有一张图像,大约每 30 秒更新一次。我正在使用画布来完成这项工作,但是当我尝试打印到画布上时,它会抛出 NPE。据我所知,画布已经初始化。活动启动视图,该视图启动/停止运行绘图方法的线程。 NPE 是在 draw 方法中抛出的。这是启动这一切的活动:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    view = new GameView(this);
    setContentView(view);
    view.onCreate();
}

public void onPause() {
    super.onPause();
    view.onPause();
}

public void onResume() {
    super.onResume();
    view.onResume();
}

这些是我的 Surface View 的主要功能:

public GameView(Context context) {
    super(context);
    getHolder().addCallback(this);
    setFocusable(true);
}

public void onCreate() {
    _drawThread = new DrawThread(getHolder(), this);
}

synchronized public void draw(Canvas canvas) {
    canvas.getHeight(); //returns NPE
}

public void onResume() {
    if (!_drawThread.isAlive()) {
        _drawThread.setRunning(true);
        _drawThread.start();
    } else {
        _drawThread.setRunning(true);
    }
}

public void onPause() {
    boolean retry = true;
    _drawThread.setRunning(false);
    while (retry) {
        try {
            _drawThread.join();
            retry = false;
        } catch (InterruptedException e) {

        }
    }
}

我的绘图线程看起来像:

public void run() {
    Canvas c;
    while (_running) {
        c = null;
        try {
            c = _surfaceHolder.lockCanvas();
            synchronized (_surfaceHolder) {
                _game.draw(c);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        } finally {
            if (c != null) {
            _surfaceHolder.unlockCanvasAndPost(c);
            }
        }
    }
}

据我所知,画布在创建导致 NPE 的绘制线程之前没有被初始化,但我看不出代码有什么问题。一点帮助或建议会很棒。

【问题讨论】:

  • 画布必须为null,_surfaceHolder.lockCanvas()返回什么?

标签: android android-canvas


【解决方案1】:

您需要使用SurfaceHolder 注册您自己的SurfaceHolder.CallbackSurfaceHolder.Callback2,并确保在尝试绘制之前已创建表面。如果您在创建表面之前尝试锁定画布,它将无法为您提供Canvas 对象。您通常不需要覆盖 SurfaceView,而只需将其用作访问您希望绘制的背面表面的机制即可。

【讨论】:

  • 我将线程设置为启动 View 的 onResume() 并停止 onPause() 但是 onResume() 直到创建表面之后才会发生。如果应用程序暂停但在重新创建表面视图之前不启动,如何防止线程绘制?
  • 好的,所以我设置线程在表面创建后开始,在表面被破坏后结束。但是,当画布被销毁时,线程仍在运行。这会导致退出活动时出现 NPE。
  • 我对你最后的评论感到困惑。如果一旦表面被破坏就停止线程,为什么线程仍在运行?您走在正确的轨道上 - 您必须通过了解表面和生命周期来管理何时将某些东西绘制到表面。
猜你喜欢
  • 2013-03-27
  • 2020-03-13
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多