我有一个带有自定义SurfaceView类和一些按钮的简单LinearLayout。以前我曾在Manifest的Activity标签中强制定位到Landscape,但是现在我需要将它定为肖像。出于某种原因,当我强制定向纵向时,不会创建SurfaceView。我通过使用单个FrameLayout来测试布局,并在我的SurfaceView类的单个实例中测试,但仍然无法正确创建。
我得到的错误取决于SurfaceView中Thread的第一个实例是什么。通常,它是onCreate中的UI线程,请求线程的句柄,这会导致NullPointerException。
为什么我的代码在横向而非肖像中工作?如果我不选择方向然后将其从横向旋转到纵向,它也会出现同样的问题。
编辑:这是我的布局:<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<stu.test.project.DrawingSurface
android:layout_width="fill_parent"
android:layout_height="700dp"
android:id="@+id/drawingSurface"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/ButtonRow1"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/ButtonRow2"/>
</LinearLayout>
</LinearLayout>
这是调用surfaceView的Activity上的onCreate,错误位于检索Thread句柄的最后一行
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawing_layout);
// Retrieve STATE and patient number from intent
bundle = this.getIntent().getExtras();
STATE = bundle.getInt("state");
patientString = bundle.getString("patientString");
//retrieveViews();
showButtons();
System.out.println("IN ONCREATE");
// Setup initial stuff if creating rather than resuming
if (savedInstanceState==null){
System.out.println("IN ONCREATE AND NO SIS");
switch(STATE){
case STATE_DRAW:
setupDraw();
break;
case STATE_LOAD:
setupLoad();
drawLoad();
break;
}
}
/* Should put Else in here
* to maybe resume data from savedInstanceState
* rather than using onSurfaceCreated as do at moment
*/
// Retrieve handle to thread
mThread = drawingSurface.getThread();
}
这是SurfaceView类,不确定什么是相关的,所以复制了所有:
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private boolean _run;
private Object mPauseLock = new Object();
private boolean mPaused;
private int STATE;
private static final int STATE_DRAW=1;
private static final int STATE_LOAD=2;
private static final int STATE_PAUSED=4;
private static final int STATE_RESUME_DRAWING=5;
private boolean finishDrawing;
private boolean startedDrawing=true;
private int resetCanvas=0;
private boolean threadRunning;
protected DrawThread thread;
boolean loaded;
public DrawingSurface(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
thread = new DrawThread(getHolder());
}
class DrawThread extends Thread{
private SurfaceHolder mSurfaceHolder;
private List<DrawingPath> mDrawingPaths;
private List<MyLine> mMyLines, backupLines;
private Paint mPaint;
public DrawThread(SurfaceHolder surfaceHolder){
mSurfaceHolder = surfaceHolder;
mDrawingPaths = Collections.synchronizedList(new ArrayList<DrawingPath>());
mMyLines = Collections.synchronizedList(new ArrayList<MyLine>());
}
public void setRunning(boolean run) {
_run = run;
}
public void setBackupLine(List<MyLine> l){
backupLines = l;
System.out.println("SETUP BACKLINE SIZE IS: "+backupLines.size());
}
// Two methods for your Runnable/Thread class to manage the Thread properly.
public void onPause() {
synchronized (mPauseLock) {
// Only pause if not finished drawing, if finished want to exit thread
if (!finishDrawing){
mPaused = true;
loaded=false;
}
}
System.out.println("Set mPaused = true");
}
public void onResume() {
synchronized (mPauseLock) {
mPaused = false;
mPauseLock.notifyAll();
}
System.out.println("Set mPaused = false");
// // Load the saved drawings or reload
// if (STATE == STATE_DRAW)
// setState(STATE_RESUME_DRAWING);
// // If loading then dont change state and instead just restart thread
// else if (STATE == STATE_LOAD){
//// resumeDrawing();
// setRunning(true);
// }
}
public boolean needToWait(){
return finishDrawing||mPaused;
}
public void setFinishDrawing(boolean b){
finishDrawing=b;
}
public void setReset(int reset){
resetCanvas=reset;
}
public void addMyLines(List<MyLine> lines){
mMyLines = lines;
}
public void addDrawingPath(DrawingPath drawingPath){
mDrawingPaths.add( drawingPath );
}
public int getSizeDrawingPaths(){
return mDrawingPaths.size();
}
public void setLoadPaint(Paint p){
mPaint = p;
}
public DrawingPath getDrawingPath(int index){
return mDrawingPaths.get(index);
}
@Override
public void run() {
while (_run){
// Set variable for running
threadRunning=true;
Canvas canvas = null;
// This code pauses the thread
synchronized (mPauseLock) {
while (mPaused) {
try {
mPauseLock.wait();
System.out.println("IN PAUSE LOOP");
} catch (InterruptedException e) {
}
}
}
try{
canvas = mSurfaceHolder.lockCanvas(null);
// Split into DRAW and LOAD
// DRAW IMAGE FROM PATHS
if (STATE == STATE_DRAW){
synchronized(mDrawingPaths) {
// If not finished drawing or resetthen draw onto canvas
if (!finishDrawing&&resetCanvas==0){
// // Draw screen white
// if (startedDrawing){
// startedDrawing=false;
// canvas.drawColor(Color.WHITE);
// System.out.println("DRAWING CANVAS WHITE");
//
// }
doDraw(canvas);
}
}
if (resetCanvas>0){
System.out.println("Resetting canvas");
if (canvas!=null)
canvas.drawColor(Color.WHITE);
resetCanvas--;
}
}
// DRAW IMAGE FROM POINTS
else if (STATE == STATE_LOAD){
doLoad(canvas, mMyLines);
// Then close the thread
setRunning(false);
}
// IF RESUMING FROM DRAWING PAUSE
else if (STATE == STATE_RESUME_DRAWING){
if (!loaded) {
doLoad(canvas, backupLines);
System.out.println("DID LOAD OF RESUME");
setState(STATE_DRAW);
loaded=true;
//setRunning(false);
}
}
}
finally {
if (canvas!=null){
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
} // While run
}
public void doDraw(Canvas c){
@SuppressWarnings("rawtypes")
Iterator i = mDrawingPaths.iterator();
while (i.hasNext()){
final DrawingPath drawingPath = (DrawingPath) i.next();
if (c==null)
System.out.println("CANVAS IS NULL");
else if (drawingPath.path==null)
System.out.println("PATH IS NULL");
else if (drawingPath.paint==null)
System.out.println("PAINT IS NULL");
if (c!=null) // Only draw to canvas if it isnt null
c.drawPath(drawingPath.path, drawingPath.paint);
}
}
public void doLoad(Canvas c, List<MyLine> lines){
// Loop through the List of lines
@SuppressWarnings("rawtypes")
Iterator i = lines.iterator();
while(i.hasNext()){
// Get the current line
final MyLine lineIt = (MyLine) i.next();
// Create new array of floating points to hold the PointFs from MyLine to draw
float prevX=0, prevY=0;
for (int j=0;j<lineIt.getSize()-1;j=j+2){
if (c==null)
System.out.println("CANVAS IS NULL");
if (j!=0&&c!=null){
c.drawLine(prevX, prevY, lineIt.getPoint(j).x, lineIt.getPoint(j+1).y, mPaint);
}
prevX = lineIt.getPoint(j).x;
prevY = lineIt.getPoint(j+1).y;
}
}
}
public void remove(int i) {
mDrawingPaths.remove(i);
}
public void clearAllPaths(){
mDrawingPaths.clear();
}
public void setState(int s){
STATE = s;
}
}
public void addDrawingPath (DrawingPath drawingPath){
thread.addDrawingPath(drawingPath);
}
public int getSizeDrawingPaths(){
return thread.getSizeDrawingPaths();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// only create thread if doesnt exist
if (!threadRunning){
thread.setRunning(true);
thread.setFinishDrawing(false);
thread.setReset(2); // Set reset to colour screen white
thread.start();
}
// // Resuming is handled in DrawingActivity's onPause override
// else {
// thread.onResume();
// }
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
// If finished drawing then close thread
// Else just want to pause thread
// if (finishDrawing){
// thread.setRunning(false);
// while (retry) {
// try {
// thread.join();
// retry = false;
// threadRunning = false; // Set threadRunning to false so creates new thread when rejoins
// } catch (InterruptedException e) {
// // we will try it again and again...
// }
// }
// }
// else {
// thread.onPause();
// System.out.println("Paused thread in SurfaceDestroyed");
// System.out.println("threadRunning is :"+threadRunning);
// }
}
public void remove(int i) {
thread.remove(i);
}
public void getDrawingPath(int i){
thread.getDrawingPath(i);
}
public void clearAllPaths(){
thread.clearAllPaths();
}
public void resetScreen(){
thread.setReset(2);
}
public void addMyLines(List<MyLine> lines){
thread.addMyLines(lines);
}
public void finishDrawing(){
thread.setFinishDrawing(true);
}
public DrawThread getThread(){
return thread;
}
public void resumeDrawing(){
thread.setFinishDrawing(false);
}
public void setState(int s){
thread.setState(s);
}
public void setLoadPaint(Paint p){
thread.setLoadPaint(p);
}
public void pauseThread(){
thread.onPause();
}
public void resumeThread(){
thread.onResume();
}
public boolean getThreadRunning(){
return threadRunning;
}
}
答案 0 :(得分:1)
您是否拥有相同的纵向和横向布局文件?
今天我有一个类似的声音小问题,我在纵向布局文件中有surfaceView但在横向布局文件中没有。由于某种原因它运行但是当我旋转设备surfaceCreated | Changed | Destroyed不再发生时。向后转,一切都很开心。