开发者

UIThread is causing problems when I want to open a new Activity

I have a SurfaceView in an Activity, and I want to open up a new Activity when something occurs in the SurfaceView(when you run out of lives - lives == 0). I've tried different things, but I keep having problems with it. If I stop my UIThread first, then of course it won't keep running and so won't be able to execute the startActivity statement. If I do start the activity, it freezes up on me and force closes - having to do with my UIThread I believe. Has anybody run into this problem before - and if so, do you have any idea how I might go about achieving this. At the very least, if I can't open up a new Activity, how could I CLOSE this current Activity (from inside the SurfaceView).

public class BoardView extends SurfaceView implements SurfaceHolder.Callback{
Context mContext;

// thread initialization
private BoardThread thread;
Thread timer;
Thread timer2;

// box variables
Bitmap box = 
    (BitmapFactory.decodeResource
            (getResources(), R.drawable.box));
private int box_x = 140;
private int box_y = 378;
private int boxWidth = box.getWidth();
private int boxHeight = box.getHeight();

// storage
private Vector<Blossom> blossomVector = new Vector<Blossom>();
Iterator<Blossom> dataIterator = blossomVector.iterator();

// counters
private int blossomNum = 0;
private String score;
private int currentScore = 0;
private int lives = 3;

boolean mode = false;
boolean game = false;

OutputStreamWriter out = null;
FileOutputStream fOut = null;

private static final String TAG = "Debug";
final Paint scorePaint = new Paint();

public BoardView(Context context){
    super(context);

    scorePaint.setColor(Color.BLACK);
    scorePaint.setTextSize(12);
    scorePaint.setTypeface(Typeface.MONOSPACE);


    //surfaceHolder provides canvas that we draw on
    getHolder().addCallback(this);

    //set up read/write data
    File root = Environment.getExternalStorageDirectory();
    File highscoresFile = new File(root, "highscores.txt");


    // controls drawings
    thread = new BoardThread(getHolder(),this, blossomVector, dataIterator, box_x, box_y, 
            boxWidth, boxHeight);

    timer2 = new Thread(){
        public void run(){
            while(game == false){
                uiCallback.sendEmptyMessage(0);
                try{
                    Thread.sleep(5000); // change to be random
                }
                catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
        }
    };

    timer = new Thread(){
        public void run(){
            //makes sure the player still has 3 lives left
            while(game == false){
                uiCallback.sendEmptyMessage(0);
                try {
                    Thread.sleep(2000); // wait two seconds before drawing the next flower
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } //sleep for 2 seconds
            }
        }
    };
    timer.start();
    timer2.start();


    //intercepts touch events
    setFocusable(true);

}


@Override

public void onDraw(Canvas canvas){
    canvas.drawColor(Color.WHITE);
    score = "SCORE: " + currentScore;

    //note: pay attention to order you draw things
    //don't change order or else blossoms will fall
    //on top of box, not "into" it.

    //display the scoreboard
    canvas.drawText(score,240,420,scorePaint);
    // uses a synchronized method to prevent concurrent modification
    DrawBlossoms(canvas);
    canvas.drawBitmap(box, box_x, box_y, null);

}

@Override
public boolean onTouchEvent(MotionEvent event){
    //handles movement of box
    if(event.getAction() == MotionEvent.ACTION_DOWN){
        if(event.getX() > box_x & event.getY() > box_y & 
                event.getX() < box_x + boxWidth & event.getY() < box_y + boxHeight)
        {
            mode = true;
        }
    }

    if(event.getAction() == MotionEvent.ACTION_MOVE) {
        if(event.getX() > box_x & event.getY() > box_y & 
                event.getX() < box_x + boxWidth & event.getY() < box_y + boxHeight)
        {
            mode = true;
        }
        if(mode == true){
            box_x = (int)event.getX();
        }   

    }

    if(event.getAction() == MotionEvent.ACTION_UP){
        mode = false;
    }

    invalidate();
    return true;
}

@Override
public void surfaceChanged(SurfaceHolder holder, 
        int format, int width, int height ){
    Log.v(TAG, "Surface Changed");
    //somehow these don't seem to be working
}

@Override
public void surfaceCreated(SurfaceHolder holder){
    thread.startRunning(true);
    thread.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder){
    Log.v(TAG, "Surface Destroyed");
    try {
    thread.join();
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

}

private Handler uiCallback = new Handler(){
    public synchronized void handleMessage(Message msg){
        //add a new blossom to the blossom Vector!!
        blossomVector.add(new Blossom( 
            (BitmapFactory.decodeResource
                    (getResources(), R.drawable.blossom))));
        dataIterator = blossomVector.iterator();
        blossomNum++;
        Log.v(TAG, "Number of Blossoms =" + blossomNum);
    }
};


private synchronized void DrawBlossoms(Canvas c) // method to draw flowers on screen and test for collision
{
    Canvas canvas = c;
    dataIterator = blossomVector.iterator();
    while (dataIterator.hasNext())
    {
        Blossom tempBlossom = dataIterator.next();
        tempBlossom.Draw(canvas);
        if (tempBlossom.hit(box_x,box_y, box_x + boxWidth, box_y + boxHeight, blossomVector) == true)
        {
            Log.v(TAG, "ITERATOR WORKS!");
            dataIterator.remove();
            currentScore += 100;
        }

        if (tempBlossom.dropped() == true)
        {
            dataIterator.remove();
            Log.v(TAG, "Blossom dropped");
            lives--;
        }
        if (lives == 0)
        {
            // stop the thread that makes blossoms
            game = true;
            //save the highscore
            try {
                File root = Environment.getExternalStorageDirectory();
                if(root.canWrite()){
                File highscoresFile = new File(root, "highscores.txt");
                FileWriter writer = new FileWriter(highscoresFile);
                BufferedWriter out = new BufferedWriter(writer);
                //out.newLine();
                out.write(score);
                out.close();
                }
            } catch (FileNotFoundException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            try {
                File root = Environment.getExternalStorageDirectory();
                File highscoresFile = new File(root, "highscores.txt");
                FileReader reader = new FileReader(highscoresFile);
                BufferedReader in = new BufferedReader(reader);
                try {
                    String scoreTest = in.readLine();
                    Log.v(TAG, "Score: " + scoreTest);
                    reader.close();

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

        try {
            thread.join();
        } catch (InterruptedException e) {
            // TO开发者_运维知识库DO Auto-generated catch block
            e.printStackTrace();
        }


        }

    }
}

}

Board Thread`public class BoardThread extends Thread {

private SurfaceHolder surfaceHolder;
private BoardView boardView;

private Vector<Blossom> blossomVector;
private int boxX;
private int boxY;
private int boxWidth;
private int boxHeight;
private boolean mrun =false;
private Iterator<Blossom> iterator;

private static final String TAG = "Debug";

public BoardThread(SurfaceHolder holder, BoardView boardView2, 
        Vector<Blossom> blossomVector1, Iterator<Blossom> dataIterator,
        int box_x, int box_y, int boxW, int boxH) {

    surfaceHolder = holder;
    boardView=boardView2;

    blossomVector = blossomVector1;
    iterator = dataIterator;
    boxX = box_x;
    boxY = box_y;
    boxW = boxWidth;
    boxH = boxHeight;
}

public void startRunning(boolean run) {

    mrun=run;
}

@Override
public void run() {

    super.run();
     Canvas canvas;
     while (mrun) {
        canvas=null;
         try {
             canvas = surfaceHolder.lockCanvas(null);
              synchronized (surfaceHolder) {
                 //update position
                 //Position(blossomVector, boxX, boxY, boxWidth, boxHeight);
                 // draw flowers
                 boardView.onDraw(canvas);
             }
         } finally {
                 if (canvas != null) {
                 surfaceHolder.unlockCanvasAndPost(canvas);
             }
         }
     }
  }

private synchronized void Position(Vector<Blossom> blossomVector,int box_x, int box_y, 
        int boxWidth, int boxHeight)
{
    //for(Blossom blossom: blossomVector)
    iterator = blossomVector.iterator();
    while (iterator.hasNext())
    {
        Blossom tempBlossom = iterator.next();
        tempBlossom.UpdatePosition();

    }
}

}

`


Sounds like the SurfaceView is running in a different thread than the main UI thread and can't modify the View objects. You'll want to create a Handler in your activity and make it accessible to your SurfaceView. Then you can send a message to the handler and it can update the UI (or launch a new activity) in the main UI thread.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜