如何在转到新活动之前杀死线程和处理程序

时间:2010-09-12 20:35:02

标签: android multithreading handler

嘿所有 - 这个代码在我试图清理处理程序的方式上可能有点乱,因为我一直试图追踪崩溃发生的地方......

我有一个对话框活动,显示一个密码条目,其中一个进度条由一个线程和处理程序设置动画......

似乎当我试图查看进度条是否完成,并试图杀死该线程时,我正在做的事情的方式是当我尝试去一个新的活动时弄乱一些东西 - 即在调用函数而没有任何东西返回或其他东西......

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 个答案:

答案 0 :(得分:7)

Thread.stop is deprecated call,您应该使用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标志,该标志允许您在线程未阻塞或休眠时停止该线程,但这是可选的。

答案 1 :(得分:2)

您可以考虑使用 AsyncTask 实例而不是runnable和处理程序。

如果需要取消AsycnTask实例,只需在AsyncTask对象引用上调用.cancel(true)即可。这将同时处理后台方法(doInBackground())和进度更新程序(onProgressUpdate())。

我通常发现AsyncTask比我自己处理所有细节更容易使用。

因此,在RMO_Dialog中,在您创建的扩展AsyncTask的类的实例上使用调用execute()

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
        }
    }

}