8

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. 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:

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

        }

    }


}
Daniel
  • 2,355
  • 9
  • 23
  • 30
Emil Øgård
  • 1,009
  • 2
  • 10
  • 12

4 Answers4

15

The following line is a problem:

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.

Just let the background task do its stuff and get any results back via onPostExecute(). Check out the following 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/");
    }


}
Daniel
  • 2,355
  • 9
  • 23
  • 30
adelphus
  • 10,116
  • 5
  • 36
  • 46
  • This fixed the app freezing, but I still get all the: "W/art: Suspending all threads took: 9.850ms" messages in the logs. I also get this: "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 Oct 14 '15 at 05:44
  • 5
    @EmilØgård These sorts of messages are common to all Apps and you shouldn't be concerned. They are simply part of the Android framework logging and used to diagnose memory management issues and debugging problems. In almost all Apps, they can be safely ignored (and you can't get rid of them). – adelphus Oct 14 '15 at 09:22
  • 2
    More specifically, the "mark sweep GC" thing is reporting what the garbage collector is doing to reclaim memory. The "suspending all threads" message is because all threads have to be suspended when the garbage collector does its work. This particular sweep took about 24 milliseconds, or about a tenth of a eye blink. ;-) – nasch Oct 14 '15 at 14:02
  • Okay, thanks. But why is it that I only output 3 lines from the website I entered? And that happens after tens of log messages. – Emil Øgård Oct 14 '15 at 15:53
  • 2
    @EmilØgård probably because you are attempting to log far too much data. The logs in logcat are designed to print short messages and will simply cut messages if they are too long. I downloaded the site you are using: the output is over 380K and the 4th line has over 13,000 characters - this is a crazy amount to try to print in a system log. Just save the output to a file or load it into a TextView if you want to see it. – adelphus Oct 15 '15 at 10:38
2

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

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

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

Niko Adrianus Yuwono
  • 11,012
  • 8
  • 42
  • 64
2

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.

You have better alternative to AsyncTask.

From "Threading Performance" article by 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.

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

Have a look at related post(s):

Handler vs AsyncTask vs Thread

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
-4

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