如何在进入新活动之前终止线程和处理程序

发布于 2024-09-19 11:51:45 字数 3922 浏览 1 评论 0原文

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

我有一个显示密码的对话框活动带有由线程和处理程序动画的进度条的条目...

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

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

            }
        }
    };
}

Hey all - this code might be a bit messy in the way I'm trying to clean up the handler as I've been trying to track down where the crash happens...

I've got a dialog activity that is showing a password entry with a progressbar being animated by a thread and handler...

It seems that when I'm attempting to see if the progressbar is done, and trying to kill the thread, the way I'm doing this is messing something up when I try to go to a new activity - ie in a way calling a function and not having anything to return to or something...

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

            }
        }
    };
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只等公子 2024-09-26 11:52:09

您可以考虑使用 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
        }
    }

}

You might consider using an AsyncTask instance instead of a runnable and a handler.

If you need to cancel an AsycnTask instance just call .cancel(true) on your AsyncTask object reference. This will take care of both the background method (doInBackground()) and the progress updater (onProgressUpdate()).

I generally find AsyncTask easier to use than trying to handle all the details myself.

So, inside RMO_Dialog, use call execute() on an instance of a class you create that extends 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
        }
    }

}
以酷 2024-09-26 11:52:03

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,并且您已经在线程体中进行处理,所以这很好。此外,您可能需要包含一个 易失性 标志,该标志允许您在线程未阻塞或休眠时停止线程,但这是可选的。

Thread.stop is deprecated call, instead you should use the Thread.interrupt method.

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 will cause a ThreadInterruptedException next time your thread blocks or sleeps and you're already handling in your thread body so that's good. Additionally, you might want to include a volatile flag that will allow you to stop the thread when it's not blocking or sleeping, but that's optional.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文