在关闭屏幕后,unlockCanvasAndPost()抛出Illegal Argument Exception之后的SurfaceHolder.lockCanvas块

时间:2015-05-19 12:25:50

标签: android android-canvas surfaceview

我有一个扩展SurfaceView的类DrawingPanel。它做了一些自定义图形的东西。它在大多数情况下工作正常,但如果显示表面并且屏幕关闭并重新打开,我会遇到问题。有时,当关闭屏幕时,unlockCanvasAndPost()会抛出IllegalArgumentException。

然后,在我重新打开屏幕后,线程启动,在包含Fragment的onResume()方法中启动,但是对lockCanvas的调用阻塞。有没有办法可以从unlockCanvasAndPost()的例外中恢复?

我可以在Galaxy Nexus和Nexus 5上重现这一点,但不是Galaxy S4和Nexus 9。

public DrawingPanel(Context context, AttributeSet attrs) {
    super(context, attrs);

    getHolder().addCallback(this);
}


@Override
public void surfaceCreated(SurfaceHolder holder) {
    Log.d(TAG, "surfaceCreated()");
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    Log.d(TAG, "surfaceChanged()");
    //Allows us to use invalidate() to call onDraw()
    setWillNotDraw(false);
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    Log.d(TAG, "surfaceDestroyed()");
    stopDrawingThread();
}

public void startDrawingThread() {
    Log.d(TAG, "startDrawingThread()");
    stopDrawingThread();
    m_thread = new PanelDrawThread(getHolder());
    m_thread.setRunning(true);
    m_thread.start();
}

public void stopDrawingThread() {
    Log.d(TAG, "stopDrawingThread()");
    // if we haven't started the thread before, there's nothing to stop.
    if(null != m_thread) {
        try {
            m_thread.setRunning(false);
            m_thread.join(1000);
        } catch (InterruptedException e) {
            Log.w(TAG, "Thread Interrupted.", e);
        }
    }
}


private class PanelDrawThread extends Thread {

    private static final long REDRAW_FRAME_SLEEP_TIME_MILLISECONDS = 20;
    private final SurfaceHolder m_surfaceHolder;
    private boolean m_isRunning;

    public void setRunning(boolean run) {
        m_isRunning = run;
    }

    public PanelDrawThread(SurfaceHolder surfaceHolder) {
        m_surfaceHolder = surfaceHolder;
    }

    @Override
    public void run() {
        Canvas canvas = null;

        while(m_isRunning) {
            if(m_redrawRequired) {
                try {
                    Log.v(TAG, "A. Locking Canvas");
                    Log.v(TAG, "A2. Canvas Surface Valid?: " + m_surfaceHolder.getSurface().isValid());
                    canvas = m_surfaceHolder.lockCanvas();
                    Log.v(TAG, "B. Canvas Locked");
                    synchronized (m_surfaceHolder) {
                        drawGraphics(canvas);
                    }
                } catch (Exception ex) {
                    Log.e(TAG, "Error drawing graphics", ex);
                } finally {
                    if (canvas != null) {
                        try {
                            Log.v(TAG, "C. Unlocking Canvas");
                            m_surfaceHolder.unlockCanvasAndPost(canvas);
                            Log.v(TAG, "D. Canvas Unlocked");

                        } catch (IllegalArgumentException iae) {
                            // ignore "Cannot unregister a locked buffer (ID=466)"
                            Log.e(TAG, "Illegal Argument Exception", iae);
                            canvas = null;
                        }
                    }
                    m_redrawRequired = false;
                }
            }
            try {
                Thread.sleep(REDRAW_FRAME_SLEEP_TIME_MILLISECONDS);
            } catch (InterruptedException e) {
                Log.e(TAG, "Error on sleep", e);
            }
        }
    }

例外:

05-19 08:22:19.855    7296-7336/my.drawing.app.android E/DrawingPanel﹕ Illegal Argument Exception
    java.lang.IllegalArgumentException
            at android.view.Surface.nativeUnlockCanvasAndPost(Native Method)
            at android.view.Surface.unlockCanvasAndPost(Surface.java:255)
            at android.view.SurfaceView$4.unlockCanvasAndPost(SurfaceView.java:844)
            at myapp.DrawingPanel$PanelDrawThread.run(DrawingPanel.java:181)

0 个答案:

没有答案