Android,在活动暂停或停止时终止线程?

时间:2015-12-16 14:25:43

标签: android multithreading

我有以下活动。当活动暂停或停止时,我希望活动内的线程终止。我搜索并找到了不适用于我的volatile布尔解决方案。当我将活动置于暂停或停止状态时,继续下载,我不想要它。

public class MyActivity extends Activity {
//some code here
   private void foo(){
   new Thread (new Runnable (){
      @Override
      public void run() {
          //download something from internet
      }
}).start();
}
}

我使用了这种无效的模式:

public class MyActivity extends Activity {
volatile Boolean state = true;
//some code here
   private void foo(){
   new Thread (new Runnable (){
      @Override
      public void run() {
        while (state) {
          //download something from internet
      }
   }
}).start();
}
@Override
public void onPause(){
super.onPause();
state = false;
}
@Override
public void onStop(){
super.onStop();
state = false;
}
}

1 个答案:

答案 0 :(得分:0)

这是一个线程结构的例子,它在击中后退时停止,这是我为我的游戏所做的(并且有效)。一个关键的区别是你在Activity中使用了一个线程,而在我的Activity中我调用了一个View,并在View中运行了一个线程。如果我回击,我会返回我的Activity,并可以通过点击'start'再次调用该线程。因为我的主题行为也是你想要你的方式,即使它发生在View中,我认为你可能会觉得它很有帮助。

我的同步发生的地方是触摸屏值,并确保在线程和调用函数中更新它们。

除非你有办法保存状态(如果你需要),否则线程会完全被删除。

您的线程需要与您希望通过线程控制/共享值的其他函数同步,例如onPause等。

**你需要在你的while循环中有一些同步的测试值,然后可以将状态改为false,否则线程将继续自己,这是线程的点。

public class GameView extends SurfaceView implements SurfaceHolder.Callback {

private final GameActivity gameActivity;
private GameThread _thread;
private boolean previouslyRunning = false;
private int width;  //Screen width
private int height; //Screen height



private boolean newGame = true;

public GameView(Context context) {
    super(context);
    getHolder().addCallback(this);
    this.gameActivity = (GameActivity) context;
    _thread = new GameThread(getHolder(), this);
    setFocusable(true);
    setFocusableInTouchMode(true);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    width = w;
    height = h;

    super.onSizeChanged(w, h, oldw, oldh);

    //_thread.initialize();
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    if (!previouslyRunning) {
        _thread = new GameThread(getHolder(), this);
        _thread.initialize();
    }

    _thread.setRunning(true);
    _thread.start();
    previouslyRunning = true;
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    //TODO - this was an Auto-generated method stub...
    //TODO - research what this might be useful for
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

    //Put stuff that needs destructed here.

    boolean retry = true;
    _thread.setRunning(false);
    while (retry) {
        try {
            _thread.join();
            retry = false;
        } catch (InterruptedException e) {
            // will will try again and again
            //TODO: figure it out....
        }
    }

}

public boolean onTouchEvent(MotionEvent event) {

    int numPointers = event.getPointerCount();
    int ptrIdx = 0;


    int touch = event.getActionMasked();

    if (touch == MotionEvent.ACTION_DOWN) {

        while (ptrIdx < numPointers) {
            int id = event.getPointerId(ptrIdx);
            float xp = event.getX(ptrIdx) / width;

            if (xp > 0.6) {
                _thread.shieldFront = false;
            }

            if (xp > 0.6 && !attacks) {
                attacks = true;
                _thread.attackandDefendToggle(true);
            } else if (xp > 0.6 && attacks) {
                attacks = false;
                _thread.attackandDefendToggle(false);
            } else if ((xp < 0.4 && xp > 0.2) && !movedRight) {
                movedRight = true;
                _thread.moveRight(true);
            } else if ((xp < 0.4 && xp > 0.2) && movedRight) {
                movedRight = false;
                _thread.moveRight(false);
            } else if (xp < 0.2 && !movedLeft) {
                movedLeft = true;
                _thread.moveLeft(true);
            } else if (xp < 0.2 && movedLeft) {
                movedLeft = false;
                _thread.moveLeft(false);
            }
            ptrIdx++;
        }
    }

    if (touch == MotionEvent.ACTION_UP) {
        _thread.moveLeft(false);
        _thread.moveRight(false);
        _thread.attackandDefendToggle(false);
        attacks = false;
        _thread.shieldFront = true;
    }



    return true;
}

class GameThread extends Thread {

    /****************************
     * Public functions       *
     ****************************/

    public GameThread(SurfaceHolder surfaceHolder, GameView panel) {
        _surfaceHolder = surfaceHolder;
        _panel = panel;

        // put sounds here.
        soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
        //more sounds later
        //TODO: create sounds
    }

    /************************************************
     *  update() function updates all variables,    *
     *  such as physics, Canvas draw points, score  *
     *  life, etc.. It is called before draw.       *
     ************************************************/
    private void update() {
        // all the values I want updated with each callback

    }

    /************************************************
     * draw() function creates images on screen,   *
     * but it performs no logic.              *
     ************************************************/
    private void draw(Canvas canvas) {

        if (canvas == null) {
            return;
        }
        //Draw stuff on screen
    }

    public void initialize() {
        // Values I want the program to start with;
    }

    public void setRunning(boolean run) {
        _run = run;
    }

    //Code below actually runs the thread.
    @Override
    public void run() {
        Canvas c;
        while (_run) {
            c = null;
            try {
                c = _surfaceHolder.lockCanvas(null);
                synchronized (_surfaceHolder) {

                    // Update the game state
                    update();

                    // Draw image
                    draw(c);
                }

            } finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state

                if (c != null) {
                    _surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}