【问题标题】:Application hangs and suspends all threads while using AsyncTask应用程序在使用 AsyncTask 时挂起并挂起所有线程
【发布时间】:2015-10-13 23:03:40
【问题描述】:

我正在尝试使用AsyncTask 类来获取网站的内容。 logcat 反复告诉我W/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();

        }

    }


}

【问题讨论】:

    标签: java android multithreading


    【解决方案1】:

    下面这行有问题:

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

    该语句的.get() 部分表示“等待任务完成”。这在任务执行时有效地阻塞了 UI 线程。

    让后台任务完成它的工作并通过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/");
        }
    
    
    }
    

    【讨论】:

    • 这修复了应用程序冻结,但我仍然在日志中收到所有:“W/art:暂停所有线程占用:9.850ms”消息。我也得到了这个:“I/art: Background partial concurrent mark sweep GC freed 58(2048B) AllocSpace objects, 45(16MB) LOS objects, 40% free, 21MB/36MB, paused 7.230ms total 23.895ms”
    • @EmilØgård 这些消息对所有应用程序都很常见,您不必担心。它们只是 Android 框架日志记录的一部分,用于诊断内存管理问题和调试问题。在几乎所有应用程序中,它们都可以被安全地忽略(而且你无法摆脱它们)。
    • 更具体地说,“标记扫描 GC”是报告垃圾收集器正在做什么来回收内存。 “暂停所有线程”消息是因为当垃圾收集器完成其工作时,所有线程都必须暂停。这种特殊的扫描耗时约 24 毫秒,或眨眼的十分之一。 ;-)
    • 好的,谢谢。但是为什么我输入的网站只输出了3行呢?这发生在数十条日志消息之后。
    • @EmilØgård 可能是因为您试图记录太多数据。 logcat 中的日志旨在打印短消息,如果消息太长,则会简单地剪切消息。我下载了您正在使用的站点:输出超过 380K,并且第 4 行有超过 13,000 个字符 - 这是尝试在系统日志中打印的疯狂数量。如果您想查看,只需将输出保存到文件或将其加载到 TextView 中。
    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      你有更好的替代AsyncTask

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

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

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

      查看相关帖子:

      Handler vs AsyncTask vs Thread

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-01-13
          • 1970-01-01
          • 1970-01-01
          • 2015-01-05
          • 2018-09-02
          • 2016-01-02
          • 2013-08-23
          • 1970-01-01
          相关资源
          最近更新 更多