我有一个扩展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)