Может ли EntityUtils.toString() вызывать исключение NetworkOnMainThreadException?

У меня есть настройка, в которой я выполняю свои http-запросы в методе doInBackground() для AsyncTask следующим образом:

@Override
protected HttpResponse doInBackground(HttpRequestBase... httpRequests)
{
    HttpResponse httpResponse = HttpClient.execute(HttpUriRequest);
    return httpResponse;
}

Этот объект HttpResponse затем передается методу onPostExecute() моего AsyncTask для передачи обработчику (первоначальному вызывающему объекту http-запроса) и обрабатывается по мере необходимости следующим образом:

  • проверка кода ответа с помощью httpResponse.getStatusLine().getStatusCode();
  • получение содержимого ответа с помощью EntityUtils.toString(httpResponse.getEntity())).

Эта настройка отлично работает на телефонах со старыми версиями Android.

Запустив мое приложение сейчас на Ice Cream Sandwich (Galaxy Nexus), я обнаружил, что первые несколько http-запросов в моем приложении, как указано выше, работают нормально, но затем есть один http-запрос, который последовательно генерирует исключение с трассировкой стека следующим образом (слегка обрезанный для читабельность):

....

в org.apache.http.util.EntityUtils.toString(EntityUtils.java:139)

в java.io.InputStreamReader.close(InputStreamReader.java:145)

в org.apache.http.conn.EofSensorInputStream.close(EofSensorInputStream.java:213)

...

на libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:151)

в android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084)

android.os.NetworkOnMainThreadException

Я сбит с толку. Означает ли это, что метод EntityUtils.toString(HttpEntity) является потенциальным виновником выбрасывания нового (и очень раздражающего) NetworkOnMainThreadException? Если да, то какие-либо советы по переделке моей настройки, чтобы делать http-запросы в отдельном потоке, чтобы ответ можно было обрабатывать в основном потоке?


person Adil Hussain    schedule 03.04.2012    source источник
comment
У меня такая же проблема, но это происходит только на некоторых телефонах и только на некоторых запросах. Иногда EntityUtils.toString работает нормально.. странно   -  person Matt Wolfe    schedule 11.09.2012
comment
Также остерегайтесь кодировки по умолчанию EntityUtils.toString: .com/questions/30642237/   -  person Christophe Roussy    schedule 25.04.2017


Ответы (1)


Пожалуйста, попробуйте следующее: измените функцию doInBackground, чтобы она возвращала значение ответа HTTP.

protected String doInBackground(HttpRequestBase... httpRequests)
{
    HttpResponse httpResponse = HttpClient.execute(HttpUriRequest);
    if (httpResponse.getEntity() != null) {
      return EntityUtils.toString(httpResponse.getEntity());
    }
    return "";
}
person Blehi    schedule 03.04.2012
comment
Это дает мне только сущность сообщения ответа. Мне также нужна строка состояния (например, HttpResponse.getStatusLine()) и, возможно, локаль ответа (например, HttpResponse.getLocale()). Думаю, мне придется извлечь все эти свойства из метода AsynTask.doInBackground(), как вы предлагаете, а затем обернуть их в мой собственный класс ServerResponse для передачи в метод onPostExecute()... если нет лучшего способа?! - person Adil Hussain; 03.04.2012
comment
Да. Вы должны сделать это таким образом. - person Blehi; 04.04.2012
comment
Вы уверены, что должны делать это именно так? Зачем этим методам работать в сети??? - person Adam; 20.11.2012
comment
Когда содержимое Entity потребляется (например, преобразуется в строку), оно считывает байты из сетевого буфера. Лично мне нравится использовать ResponseHandler и возвращать объект результата, но имейте в виду, что Android отходит от Apache HttpClient (см. android-developers.blogspot.com/2011/09/). - person Sofi Software LLC; 11.02.2013