【问题标题】:How to kill a thread and handler before going to new activity如何在进行新活动之前杀死线程和处理程序
【发布时间】:2010-09-12 20:35:01
【问题描述】:

大家好——这段代码在我试图清理处理程序时可能有点混乱,因为我一直在试图追踪崩溃发生的位置......

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

似乎当我尝试查看进度条是否已完成并尝试终止线程时,当我尝试进行新活动时,我这样做的方式会搞砸一些事情 - 即在调用函数并且没有任何东西可以返回 to 或其他东西的方式......

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();
                }

            }
        }
    };
}

【问题讨论】:

  • 我修正了你的格式,别忘了选择你的代码并点击代码格式化按钮 (101010)...你也可以在之后格式化你的代码您可以通过点击问题下方的编辑来提交您的问题。

标签: android multithreading handler


【解决方案1】:

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 标志,它允许您在线程未阻塞或休眠时停止线程,但这是可选的。

【讨论】:

  • 很好的解释,特别是对于我没有在我的 Android 应用程序中处理的异常。你帮我理解了谢谢!
  • @Zonata 太棒了!另外 - 请不要忘记通过单击左侧的复选标记(就在投票下方)来接受最能解决您问题的问题。
  • Lirik - 我愿意,但这不是我的问题;)
【解决方案2】:

您可以考虑使用 AsyncTask 实例而不是可运行对象和处理程序。

如果您需要取消 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
        }
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-14
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多