Как убить поток и обработчик перед переходом к новому действию - PullRequest
4 голосов
/ 13 сентября 2010

Привет всем - этот код может быть немного беспорядочным в том смысле, что я пытаюсь очистить обработчик, когда пытаюсь отследить, где происходит сбой ...

У меня есть диалоговое действие, которое показывает ввод пароля с индикатором выполнения, анимированным потоком и обработчиком ...

Кажется, что когда я пытаюсь увидеть, завершен ли индикатор выполнения, и пытаюсь убить поток, то, что я делаю, это что-то портит, когда я пытаюсь перейти к новому действию - т.е. в способ вызова функции и отсутствие возможности вернуть в или что-то ...

public class RMO_Dialog extends Activity {
    private ProgressBar progbar;
    private Button dialogOK;
    private EditText dialogPass;
    private SharedPreferences prefs;
    private String pass;
    private int increment=10;
    private Thread background;

    private Boolean commCalled=false;

    public void callCommunications(){
        progbar.setVisibility(0);
        progbar.setProgress(0);
        background.stop();
        Toast.makeText(getApplicationContext(), "Call communication should happen once.", Toast.LENGTH_LONG).show();
//      Intent i = new Intent();
//      i.setClass(RMO_Dialog.this, RMO_Comm.class);
//      i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//      startActivity(i);
//          finish();
    }

    public void buzzUser(){

        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        int dot = 200;
        int dash = 500;
        int short_gap = 200;
        int medium_gap = 500;
        int long_gap = 1000;
        long[] pattern = {0,dot, short_gap, dot, short_gap, dot, medium_gap, dash, short_gap, dash, short_gap, dash, medium_gap, dot, short_gap, 
                dot, short_gap, dot, long_gap};

        v.vibrate(pattern, -1);


    }

    public void killCountdown(){
        progbar.setVisibility(0);
        progbar.setProgress(0);
        background.stop();
    }

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.dialogpassword);

        buzzUser();

        prefs = this.getSharedPreferences("RMO", MODE_WORLD_READABLE);
        pass = prefs.getString("password", "");

        dialogOK = (Button) findViewById(R.id.dialogOK);
        dialogPass = (EditText) findViewById(R.id.dialogPass);
        progbar = (ProgressBar) findViewById(R.id.progress);

        progbar.setProgress(0);

        background = new Thread(new Runnable(){
            @Override
            public void run() {
                try{
                    while(progbar.getProgress()<=progbar.getMax()){
                        Thread.sleep(300);
                        progressHandler.sendMessage(progressHandler.obtainMessage());
                    }
                }catch(java.lang.InterruptedException e){
                    Toast.makeText(getApplicationContext(), "Error thrown.", Toast.LENGTH_LONG).show();
                }

            }

        });
        background.start();

        dialogOK.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(dialogPass.getText().toString().equals(pass.toString())){
                    killCountdown();
                    Toast.makeText(getApplicationContext(), "Guardian Angel next alert has been disengaged.", Toast.LENGTH_LONG).show();
                    Intent intent = new Intent();
                    intent.setClass(RMO_Dialog.this, RMO.class);
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                    finish();
                }else{
                    callCommunications();
                }
            }
        });



    }

    Handler progressHandler = new Handler(){
        public void handleMessage(Message msg){
            progbar.incrementProgressBy(increment);
            if(progbar.getProgress()==progbar.getMax()){
                Toast.makeText(getApplicationContext(), "commcalled: "+ commCalled, Toast.LENGTH_LONG).show();
                if(commCalled==false){
                    commCalled=true;
                    callCommunications();
                }

            }
        }
    };
}

Ответы [ 2 ]

7 голосов
/ 13 сентября 2010

Thread.stop устарел: вызов , вместо этого следует использовать метод Thread.interrupt .

public void killCountdown(int waitTime){
    progbar.setVisibility(0);
    progbar.setProgress(0);
    // deprecated: background.stop();
    background.interrupt(); // <-- OK
    background.join(waitTime); // optionally wait for the thread to exit
}

Thread.Interrupt вызовет ThreadInterruptedException в следующий раз, когда ваш поток блокируется или засыпает, и вы уже работаете с телом потока, так что это хорошо. Кроме того, вы можете включить флаг volatile, который позволит вам остановить поток, когда он не блокируется или не спит, но это необязательно.

2 голосов
/ 13 ноября 2011

Вы можете рассмотреть возможность использования AsyncTask экземпляра вместо runnable и обработчика.

Если вам нужно отменить экземпляр AsycnTask, просто вызовите .cancel(true) в ссылке на объект AsyncTask. Это позаботится как о фоновом методе (doInBackground()), так и о программе обновления прогресса (onProgressUpdate()).

Как правило, AsyncTask проще использовать, чем пытаться обрабатывать все детали самостоятельно.

Итак, внутри RMO_Dialog используйте вызов execute() для экземпляра создаваемого вами класса, расширяющего AsyncTask.

public class RMO_Dialog extends Activity {

    ...
    // Get ref to your bg task for easily cancellation if needed
    PassWordEntry background = new PassWordEntry();
    // Start bg task
    background.execute([PARAMS]);
    ...
    // Cancel task
    background.cancel(true);
    ...

    // AsyncTask lets you encapsulate both your runnable and handler in it
    private static class PassWordEntry() extends AsyncTask<[PARAMS], [PROGRESS], [RESULT]> {
        protected [RESULT] doInBackground() {
            ... // Runnable stuff here
            return [RESULT];
        }

        protected void onProgressUpdate([PROGRESS]... progress) {
            ... // progressHandler stuff here
        }

        protected void onPostExecute([RESULT]) {           
            // Clean up return data when all done w BG here
        }
    }

}
...