记录SurfaceView使用的一个错误解决方法。
错误打印:
09-03 20:04:49.543 15962-16033/com.dway.mediaplayer E/Surface: queueBuffer: error queuing buffer to SurfaceTexture, -19
queueBuffer (handle=0x7f789d0d20) failed (No such device)
--------- beginning of crash
09-03 20:04:49.544 15962-16033/com.dway.mediaplayer E/AndroidRuntime: FATAL EXCEPTION: Thread-3
Process: com.dway.mediaplayer, PID: 15962
java.lang.IllegalArgumentException
at android.view.Surface.nativeUnlockCanvasAndPost(Native Method)
at android.view.Surface.unlockSwCanvasAndPost(Surface.java:347)
at android.view.Surface.unlockCanvasAndPost(Surface.java:328)
at android.view.SurfaceView$4.unlockCanvasAndPost(SurfaceView.java:1045)
at com.dway.DrawView.draw(DrawView.java:82)
at com.dway.DrawView.run(DrawView.java:46)
at java.lang.Thread.run(Thread.java:761)
代码:
package com.dway.player;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class DrawView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder mSurfaceHolder;
private Canvas mCanvas;
private Path mPath = new Path();
private Paint mPaint = new Paint();
private boolean mIsDraw;
public DrawView(Context context) {
super(context);
initView();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mSurfaceHolder = getHolder();
mSurfaceHolder.addCallback(this);
}
@Override
public void run() {
while (mIsDraw) {
draw();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
mIsDraw = true;
new Thread(this).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mIsDraw = false;
}
//解决错误增加的方法
public void exit(){
mIsDraw = false;
}
private void draw() {
try {
mCanvas = mSurfaceHolder.lockCanvas();
mCanvas.drawColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPaint.setColor(Color.BLACK);
mCanvas.drawPath(mPath, mPaint);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mCanvas != null) {
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPath.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
mPath.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
初看这代码好像没什么问题,但是当手指一次在屏幕上滑动很久之后,点击返回键退出就会出现错误,而且错误是native下的错误。
Activity跑了onPause后已经退出视野,并且堆栈下面的一个Activity也已经onResume了,但是SurfaceView更新线程还未停止,因为SurfaceView要等到回调destroy才停止,所以可能导致unlockCanvasAndPost方法出错,具体怎么出错还不知。
但是还是可以解决的,增加了exit方法,并且在Activity的finish方法中把绘制线程先停掉,这样就没问题了。
@Override
public void finish() {
super.finish();
DrawView drawView = findViewById(R.id.draw_view);
drawView.exit();
}
有知道具体原因的可以告知下,谢谢。