简体   繁体   English

如何停止或销毁 Android 线程

[英]How to stop or destroy an Android thread

I know that the stop method has been deprecated and I am using destroy now, but I get this error:我知道stop方法已被弃用,我现在正在使用destroy ,但我收到此错误:

11-09 11:42:28.740: E/AndroidRuntime(1538): FATAL EXCEPTION: main
11-09 11:42:28.740: E/AndroidRuntime(1538): java.lang.NoSuchMethodError: Thread.destroy()
11-09 11:42:28.740: E/AndroidRuntime(1538):     at java.lang.Thread.destroy(Thread.java:600)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.rathbones.src.NewslettersActivity.onKeyDown(NewslettersActivity.java:144)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.KeyEvent.dispatch(KeyEvent.java:1037)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.app.Activity.dispatchKeyEvent(Activity.java:2068)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1643)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2471)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2441)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1735)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.os.Looper.loop(Looper.java:123)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at android.app.ActivityThread.main(ActivityThread.java:4627)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at java.lang.reflect.Method.invokeNative(Native Method)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at java.lang.reflect.Method.invoke(Method.java:521)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
11-09 11:42:28.740: E/AndroidRuntime(1538):     at dalvik.system.NativeStart.main(Native Method)
11-09 11:42:28.760: W/ActivityManager(59):   Force finishing activity com.rathbones.src/.NewslettersActivity

The application is not crashing, it's just that I get this error in logcat.应用程序没有崩溃,只是我在 logcat 中收到此错误。

Actually I have a newsletter module which enables users to view the PDF file.实际上我有一个通讯模块,它使用户能够查看 PDF 文件。 When they press the view button it opens up a progress bar and in the same time if someone presses the backbutton it should stop the thread and exit gracefully.当他们按下查看按钮时,它会打开一个进度条,同时如果有人按下后退按钮,它应该停止线程并优雅地退出。 It does that but in the log I get the above error.它这样做了,但在日志中我收到了上述错误。

Here is the code snippet causing this error:这是导致此错误的代码片段:

private void viewOnline() {

        if (currentNewsletter == null) {
            Log.e(Constants.APP_NAME, "No newsletter selected");
            return;
        }

        final ProgressDialog d = new ProgressDialog(this);
        d.setMessage("Downloading...");
        d.show();

        final Context context = getApplicationContext();
         t = new Thread(new Runnable() {
            public void run() {

                String fileName = currentNewsletter.mFilename;

                Log.d(Constants.APP_NAME, "Downloading/showing: " + fileName);
                final File file = Utilities.getFileFromURL(context, currentNewsletter.mUrl, currentNewsletter.mExpectedSizeInBytes, fileName, false);

                d.dismiss();
                // Now we can show the file
                viewPDF(file);
            }
        });
        t.start();

        // Utilities.List(getApplicationContext().getFilesDir().getPath());
        // Utilities.List(getApplicationContext().getDir("files", Context.MODE_WORLD_WRITEABLE).getAbsolutePath());
        // Utilities.DeleteDirectory(getApplicationContext().getDir("files", Context.MODE_WORLD_WRITEABLE).getAbsolutePath());

    }

    private void viewPDF(File file) {

        //DEBUG DEBUG DEBUG
        //Log.d(Constants.APP_NAME, "ViewPDF: showing " + file.getName());
        //Log.d(Constants.APP_NAME, "Path: " + file.getPath());
        //Log.d(Constants.APP_NAME, "Exists: " + file.exists());
        //Log.d(Constants.APP_NAME, "Length: " + file.length());
        //DEBUG DEBUG DEBUG

        // Now it's all safe and sound and local, open it
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setDataAndType(Uri.fromFile(file), "application/pdf");

        try {
            startActivity(intent);
        } catch (Exception e) {
            Toast.makeText(this, "No Application Available to View PDF", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onStop() {
        finish();
        super.onStop();
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            t.destroy();
           Intent i = new Intent(NewslettersActivity.this,MainMenuActivity.class);

           startActivity(i);
           finish();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

If you have a thread with a while loop inside, you can control this thread by a boolean flag for the while condition.如果您有一个带有while循环的线程,您可以通过 while 条件的布尔标志来控制该线程。 When you set the flag to false the thread just finishes its task.当您将标志设置为 false 时,线程就完成了它的任务。

Here's a little example:这是一个小例子:

boolean flag = true;
Thread secondary = new Thread(new Runnable() {

@Override
public void run() {
    while (flag) {
    // do something
    }
 }
});

secondary.start(); //start the thread
flag = false; // this will force secondary to finish its execution
 try {
   secondary.join(); // wait for secondary to finish
   } catch (InterruptedException e) {
    throw new RuntimeException(e);
}

I will found this code in SO and it also works for me.我会在 SO 中找到这段代码,它也适用于我。

使用interrupt()而不是destroy()

To the user370305 answer, maybe two changes could help:对于 user370305 的回答,也许有两个变化会有所帮助:

  1. Use AtomicBoolean instead boolean, if the Thread runs in another core, changes could not be visible for flag.使用AtomicBoolean代替 boolean,如果 Thread 在另一个核心中运行,则标志的更改将不可见。

  2. Remove the throw new RuntimeException(e) within the catch.删除 catch 中的throw new RuntimeException(e) It will crash as you are throwing an Exception.它会在您抛出异常时崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM