Java 应用程序在使用 AsyncTask 时挂起并挂起所有线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33114036/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:20:41  来源:igfitidea点击:

Application hangs and suspends all threads while using AsyncTask

javaandroidmultithreading

提问by Emil ?g?rd

I am trying to use the AsyncTaskclass to get a website's content. The logcat tells me W/art: Suspending all threads took: 15(or any other number)msrepeatedly. My application is frozen until the log messages are done printing. UI shows up after the log is done. I followed a tutorial and have double checked that my code should be the same as the tutorial. After a while, it logs a few lines of code from the website, but nothing more. I tried with different websites as well. Here is my AsyncTask:

我正在尝试使用AsyncTask该类来获取网站的内容。logcatW/art: Suspending all threads took: 15(or any other number)ms反复告诉我。我的应用程序被冻结,直到日志消息打印完成。日志完成后显示 UI。我遵循了教程并仔细检查了我的代码是否应该与教程相同。过了一会儿,它从网站上记录了几行代码,但仅此而已。我也尝试过不同的网站。这是我的 AsyncTask:

public class MainActivity extends AppCompatActivity {

    public class DownloadTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... urls) {

            String result = "";
            URL url;
            HttpURLConnection urlConnection = null;

            try {

                url = new URL(urls[0]);

                urlConnection = (HttpURLConnection) url.openConnection();

                InputStream in = urlConnection.getInputStream();

                InputStreamReader reader = new InputStreamReader(in);

                int data = reader.read();

                while (data != -1) {

                    char current = (char) data;

                    result += current;

                    data = reader.read();

                }

                return result;

            } catch (Exception e) {

                e.printStackTrace();

            }

            return null;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DownloadTask task = new DownloadTask();
        String result = null;

        try {

            result = task.execute("http://www.vg.no/").get();

            Log.i("URL content" , result);

        } catch (InterruptedException e) {

            e.printStackTrace();

        } catch (ExecutionException e) {

            e.printStackTrace();

        }

    }


}

采纳答案by adelphus

The following line is a problem:

以下行是一个问题:

result = task.execute("http://www.vg.no/").get();

result = task.execute("http://www.vg.no/").get();

The .get()part of this statement means "wait until the task completes". This effectively blocks the UI thread while the task executes.

.get()语句的部分意思是“等到任务完成”。这在任务执行时有效地阻止了 UI 线程。

Just let the background task do its stuff and get any results back via onPostExecute(). Check out the following AsyncTask:

只需让后台任务完成它的工作并通过onPostExecute(). 查看以下 AsyncTask:

public class MainActivity extends AppCompatActivity {

   public class DownloadTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... urls) {
            ...
        }

        @Override
        protected void onPostExecute(String result) {
            Log.i("URL content" , result);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DownloadTask task = new DownloadTask();
        task.execute("http://www.vg.no/");
    }


}

回答by Niko Adrianus Yuwono

First of all I think you misused AsyncTask. AsyncTask should be used asynchronously not synchronously using get().

首先,我认为您误用了 AsyncTask。AsyncTask 应该异步使用,而不是使用 get() 同步使用。

you should add onPostExecute inside your AsyncTask and get the result there.

您应该在 AsyncTask 中添加 onPostExecute 并在那里获得结果。

protected void onPostExecute(String result) {
     //You could get the result here
}

You could read better tutorial here -> http://developer.android.com/reference/android/os/AsyncTask.html

你可以在这里阅读更好的教程 - > http://developer.android.com/reference/android/os/AsyncTask.html

回答by Halit Onur Karaba?

I got the same problem in such a way. "while" is the reason of your problem, you need to get rid of it.

我以这种方式遇到了同样的问题。“while”是您问题的原因,您需要摆脱它。

回答by Ravindra babu

I am trying to use the AsyncTask class to get a website's content. The logcat tells me W/art: Suspending all threads took: 15(or any other number)ms repeatedly.

我正在尝试使用 AsyncTask 类来获取网站的内容。logcat 告诉我 W/art:暂停所有线程花费:15(或任何其他数字)重复。

You have better alternative to AsyncTask.

你有更好的替代AsyncTask

From "Threading Performance" article by developer.android.com:

来自developer.android.com 的线程性能”文章:

When using AsyncTask, there are a few important performance aspects to keep in mind. First, by default, an app pushes all of the AsyncTask objects it creates into a single thread. Therefore, they execute in serial fashion, and—as with the main thread—an especially long work packet can block the queue. For this reason, we suggest that you only use AsyncTask to handle work items shorter than 5ms in duration.

使用 AsyncTask 时,需要牢记一些重要的性能方面。首先,默认情况下,应用将其创建的所有 AsyncTask 对象推送到单个线程中。因此,它们以串行方式执行,并且与主线程一样,特别长的工作包可能会阻塞队列。因此,我们建议您仅使用 AsyncTask 来处理持续时间短于 5ms 的工作项。

You can use HandlerThreadas an alternative. If you have many URLs to be fetched, go for ThreadPoolExecutor

您可以使用HandlerThread作为替代。如果您要获取很多 URL,请使用ThreadPoolExecutor

Have a look at related post(s):

看看相关帖子:

Handler vs AsyncTask vs Thread

处理程序 vs AsyncTask vs 线程