简体   繁体   中英

ending android activity from surfaceview using thread.join

I'm working on my first app for android - snake. Right now I'm trying to implement 'game over' for that app. So basically when the snake hits the wall, app should ask your name and put it witch your score on HiScore. Well i'm stuk on hitting the wall fragment. Im experimenting with threads and so far I've found no way to stop it without getting errors.

I googled a lot, and everyone is saying that thread.join(); is waiting for thread to end, so how long does it take to end the thread that is drawing simple squares once per half second? When im hitting the back button on my phone while playing, pause(); function works perfectly. Log "game has ended" appears on LogCat.

So the problem is that i cant stop this activity when snake hits the wall, Log "game has ended" never occurs. Why is that?

My code:

public class SnakeCage extends SurfaceView implements Runnable{

    // blah blah .. functions that draw and stuff ..


    public void pause() {
        isRunning = false;
        while(true){
            try {
                aThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;
        }
        aThread = null;
    Log.d("pause()","game has ended"); // <<<<<<<<<THIS ONE>>>>>>>>>
    }

    public void resume() {
        isRunning = true;       
        aThread = new Thread(this);
        aThread.start();
    }

    public void init(){
        // blah blah...
    }


    private void gameOver() {
    int pHeadX = snakeHead.posX;
    int pHeadY = snakeHead.posY;

        Log.d("gameOver()", "checking");

        if(pHeadY<0 || pHeadX<0 || pHeadX>23 || pHeadY>19){

            Log.d("gameOver()", "game now will end");
            gameOver = true;
        }
    }

    public void run() {

        while (isRunning){
            if(!aHolder.getSurface().isValid())
                continue;

            canvas = aHolder.lockCanvas();

            // drawing

            gameOver();
            if(gameOver) break;

            // more drawing 


            aHolder.unlockCanvasAndPost(canvas);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if(gameOver){
                 pause();
        }
    }

and the activity class:

public class PlayingActivity extends Activity implements OnClickListener{

    SnakeCage v;
    Button snakeGoUp;
    Button snakeGoDown;
    Button snakeGoLeft;
    Button snakeGoRight;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);     

        setContentView(R.layout.frame_layout);
        v = (SnakeCage)findViewById(R.id.sView);

        // listeners and stuff

    }


    @Override
    protected void onPause() {
        super.onPause();
        v.pause();
    }


    @Override
    protected void onResume() {
        super.onResume();
        v.resume();
    }


    @Override
    public void onClick(View view) {
        switch(view.getId()){

        case R.id.snakeUp:
            v.move(1);
            break;

        case R.id.snakeDown:
            v.move(2);
            break;

        case R.id.snakeLeft:
            v.move(3);
            break;

        case R.id.snakeRight:
            v.move(4);
            break;
        }

    }
}

i just did:

Context context = getContext();
((PlayingActivity)context).finish();

from:

How can I end an activity from inside a SurfaceView class or nested thread

although it does not satisfy me... its enough for now

I would suggest using a LocalBroadcastManager to send a message to the Activity , to notify it to kill itself. You can have an inner class in the Activity to receive the broadcast and call a private method in the Activity which will end it.

public class MyActivity extends Activity {

    public void onCreate(Bundle state) {
        LocalBroadcastManager.getInstance(this).registerReceiver(new MessageHandler(),
                                                             new IntentFilter("kill"));
    }

    private void killActivity() {
        finish();
    }

    public class MessageHandler extends BroadcastReceiver {
        onReceive(Context context, Intent intent) {
            killActivity();
        }

}

Then in your SurfaceView all you need to do is:

Intent intent = new Intent("kill");
LocalBroadcastManager.getInstance(getContext()).sendBroadcast(intent);

Its a little more code but its a lot cleaner IMHO.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM