Я получил ошибку при запуске моего проекта Android для RssReader.
Код:
URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();
И это показывает следующую ошибку:
android.os.NetworkOnMainThreadException
Как я могу исправить эту проблему?
java
android
android-networking
networkonmainthread
радуйся джордж
источник
источник
Ответы:
Это исключение выдается, когда приложение пытается выполнить сетевую операцию в своем основном потоке. Запустите ваш код в
AsyncTask
:Как выполнить задачу:
В
MainActivity.java
файле вы можете добавить эту строку в свойoncreate()
методНе забудьте добавить это в
AndroidManifest.xml
файл:источник
AsyncTask
, и заботится об изменении конфигурации.Вы должны почти всегда запускать сетевые операции в потоке или как асинхронную задачу.
Но это возможно , чтобы удалить это ограничение и переопределить поведение по умолчанию, если вы готовы принять последствия.
Добавить:
В вашем классе
а также
ДОБАВЬТЕ это разрешение в файл android manifest.xml:
Последствия:
Ваше приложение (в местах с нестабильным интернет-соединением) перестает отвечать и блокируется, пользователь чувствует медлительность и вынужден принудительно убивать, а вы рискуете, что менеджер активности убьет ваше приложение и сообщит пользователю, что приложение остановлено.
В Android есть несколько полезных советов о том, как правильно программировать, чтобы создавать адаптивные решения: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html.
источник
doInBackground
объявление, 2 закрывающих скобки и вызовexecute()
). С другой стороны, даже одна выборка с сайта, о которой вы упомянули, приводит к значительному отставанию скорости отклика пользовательского интерфейса. Не ленись.Я решил эту проблему с помощью нового
Thread
.источник
Принятый ответ имеет несколько существенных недостатков. Не рекомендуется использовать AsyncTask для работы в сети, если вы действительно не знаете, что делаете. Некоторые из недостатков включают в себя:
executeOnExecutor
метод и не предоставляете альтернативного исполнителя). Код, который отлично работает при последовательной работе на ICS, может быть поврежден при одновременном выполнении на Gingerbread, например, если у вас есть непреднамеренные зависимости порядка выполнения.Если вы хотите избежать кратковременных утечек памяти, иметь четко определенные характеристики выполнения на всех платформах и иметь базу для построения действительно надежной сетевой обработки, вы можете рассмотреть следующие вопросы:
Service
илиIntentService
вместо, возможно с,PendingIntent
чтобы возвратить результат черезonActivityResult
метод действия.IntentService подход
Down-сторона:
AsyncTask
, хотя и не так много, как вы думаетеIntentService
эквивалентнойService
реализацией, возможно, такой .Вверх-стороны:
onActivityResult
метода.AsyncTask
вActivity
, но если пользователь контекста переключается из приложения , чтобы сделать телефонный звонок, система может убить приложение до того , как завершает загрузку. Это менее вероятно , чтобы убить приложение с активнымService
.IntentService
(например, ту, которую я упомянул выше), вы можете контролировать уровень параллелизма черезExecutor
.Краткое описание реализации
Вы можете реализовать
IntentService
загрузку в одном фоновом потоке.Шаг 1: Создайте
IntentService
для выполнения загрузки. Вы можете указать, что загружать с помощьюIntent
extra's, и передать егоPendingIntent
для использования, чтобы вернуть результатActivity
:Шаг 2: Зарегистрируйте сервис в манифесте:
Шаг 3: Вызовите сервис из Activity, передав объект PendingResult, который Сервис будет использовать для возврата результата:
Шаг 4: обработать результат в onActivityResult:
Проект Github, содержащий полностью работающий проект Android-Studio / Gradle, доступен здесь .
источник
IllustrativeRSS
? Что если вы не работаете с RSS?AsyncTask
. Ошибка должна была помешать разработчикам отстать от пользовательского интерфейса, не обязательно побуждая их рисковать безопасностью с помощью множества намерений / сервисов.Вы не можете выполнять сетевой ввод / вывод в потоке пользовательского интерфейса на сотовой основе . Технически, это является возможно на более ранних версиях Android, но это действительно плохая идея , так как это приведет ваше приложение перестает отвечать на запросы, и может привести к ОС убивает ваше приложение для того плохо себя вели. Вам нужно будет запустить фоновый процесс или использовать AsyncTask для выполнения вашей сетевой транзакции в фоновом потоке.
На сайте разработчиков Android есть статья о Painless Threading, которая является хорошим введением в это, и она даст вам гораздо более глубокую глубину ответа, чем это можно реально представить здесь.
источник
Использовать сервис или AsyncTask
Смотрите также вопрос переполнения стека:
android.os.NetworkOnMainThreadException отправка электронного письма с Android
источник
Делать сетевые действия в другом потоке
И добавьте это в AndroidManifest.xml
источник
Вы отключаете строгий режим, используя следующий код:
Это не рекомендуется : используйте
AsyncTask
интерфейс.Полный код для обоих методов
источник
Сетевые операции не могут выполняться в главном потоке. Вам нужно запустить все сетевые задачи в дочернем потоке или реализовать AsyncTask.
Вот как вы запускаете задачу в дочернем потоке:
источник
Поместите свой код внутри:
Или:
источник
Это происходит в Android 3.0 и выше. Начиная с Android 3.0 и выше, они ограничивали использование сетевых операций (функций, имеющих доступ к Интернету) в основном потоке / потоке пользовательского интерфейса (что порождается вашими методами создания и возобновления в действии).
Это должно поощрять использование отдельных потоков для сетевых операций. См. AsyncTask для более подробной информации о том, как правильно выполнять сетевые операции.
источник
Использование Android Аннотации является опцией. Это позволит вам просто запустить любой метод в фоновом потоке:
Обратите внимание, что, хотя он обеспечивает преимущества простоты и удобочитаемости, он имеет свои недостатки.
источник
Ошибка связана с выполнением длительных операций в главном потоке. Вы можете легко устранить проблему с помощью AsynTask или Thread . Вы можете проверить эту библиотеку AsyncHTTPClient для лучшей обработки.
источник
Вы не должны выполнять никаких трудоемких задач в главном потоке (потоке пользовательского интерфейса), таких как сетевые операции, операции ввода-вывода файлов или операции с базами данных SQLite. Таким образом, для такого рода операций вы должны создать рабочий поток, но проблема в том, что вы не можете напрямую выполнять какие-либо операции, связанные с пользовательским интерфейсом, из вашего рабочего потока. Для этого вы должны использовать
Handler
и передатьMessage
.Чтобы упростить все эти вещи, Android предоставляет различные способы, такие как
AsyncTask
,AsyncTaskLoader
,CursorLoader
илиIntentService
. Таким образом, вы можете использовать любой из них в соответствии с вашими требованиями.источник
Верхний ответ спектом работает отлично.
Если вы пишете
AsyncTask
inline, а не расширяете как класс, и, кроме того, если есть необходимость получить ответAsyncTask
, можно использоватьget()
метод, как показано ниже.(Из его примера.)
источник
get()
- плохая идея ... это делает AsyncTask снова "синхронизированным"Это выбрасывается только для приложений, ориентированных на Honeycomb SDK или выше. Приложениям, нацеленным на более ранние версии SDK, разрешено создавать сети в своих основных потоках цикла событий.
Ошибка - предупреждение SDK!
источник
Для меня это было так:
Устройство, на котором я тестировал мое приложение, было 4.1.2, то есть SDK версии 16!
Убедитесь, что целевая версия совпадает с целевой библиотекой Android. Если вы не знаете, какая у вас целевая библиотека, щелкните правой кнопкой мыши на Project -> Build Path -> Android , и она должна быть отмечена галочкой.
Также, как уже упоминали другие, включите правильные разрешения для доступа в Интернет:
источник
NetworkOnMainThreadException
Страж, который говорит вам: не стреляйте себе в ногу ... Ваше решение: давайте вернемся в прошлое, когда не было Стража - теперь я могу стрелять по своим ноги свободноИспользуйте это в своей деятельности
источник
Просто, чтобы объяснить что-то явно:
Основной поток - это в основном поток пользовательского интерфейса.
То, что вы не можете выполнять сетевые операции в основном потоке, означает, что вы не можете выполнять сетевые операции в потоке пользовательского интерфейса, что означает, что вы также не можете выполнять сетевые операции в
*runOnUiThread(new Runnable() { ... }*
блоке внутри какого-то другого потока.(У меня просто был долгий головокружительный момент, когда я пытался выяснить, почему я получаю эту ошибку где-то, кроме моего основного потока. Вот почему; этот поток помог; и, надеюсь, этот комментарий поможет кому-то еще.)
источник
Это исключение возникает из-за любой тяжелой задачи, выполняемой в главном потоке, если выполнение этой задачи занимает слишком много времени .
Чтобы избежать этого, мы можем справиться с этим с помощью потоков или исполнителей
источник
На этот вопрос уже есть много хороших ответов, но с тех пор, как эти ответы были опубликованы, появилось много замечательных библиотек. Это задумано как своего рода новичок-гид.
Я расскажу о нескольких случаях использования для выполнения сетевых операций и одном или двух решениях для каждого.
ReST через HTTP
Как правило, Json, может быть XML или что-то еще
Полный доступ к API
Допустим, вы пишете приложение, которое позволяет пользователям отслеживать цены на акции, процентные ставки и курсы валют. Вы найдете Json API, который выглядит примерно так:
Дооснащение от площади
Это отличный выбор для API с несколькими конечными точками и позволяет объявлять конечные точки ReST вместо того, чтобы кодировать их по отдельности, как в других библиотеках, таких как ion или Volley. (веб-сайт: http://square.github.io/retrofit/ )
Как вы используете его с API финансов?
build.gradle
Добавьте эти строки на уровень вашего модуля buid.gradle:
FinancesApi.java
FinancesApiBuilder
ФинансыФрагмент фрагмента
Если вашему API требуется отправить ключ API или другой заголовок, например, токен пользователя и т. Д., Retrofit упрощает эту задачу (подробности см. В этом удивительном ответе: https://stackoverflow.com/a/42899766/1024412 ).
Одноразовый доступ к API ReST
Допустим, вы создаете приложение «погода настроения», которое ищет местоположение GPS пользователей, проверяет текущую температуру в этой области и сообщает им настроение. Приложение такого типа не должно объявлять конечные точки API; ему просто нужно иметь доступ к одной конечной точке API.
ион
Это отличная библиотека для этого типа доступа.
Пожалуйста, прочитайте отличный ответ msysmilu ( https://stackoverflow.com/a/28559884/1024412 )
Загрузка изображений через HTTP
залп
Залп может также использоваться для API ReST, но из-за более сложной настройки я предпочитаю использовать Retrofit from Square, как указано выше ( http://square.github.io/retrofit/ )
Допустим, вы создаете приложение для социальных сетей и хотите загрузить фотографии друзей.
build.gradle
Добавьте эту строку на уровень вашего модуля buid.gradle:
ImageFetch.java
Залп требует больше настроек, чем модификация. Вам нужно будет создать такой класс, чтобы настроить RequestQueue, ImageLoader и ImageCache, но это не так уж плохо:
user_view_dialog.xml
Добавьте следующее в ваш XML-файл макета, чтобы добавить изображение:
UserViewDialog.java
Добавьте следующий код в метод onCreate (Fragment, Activity) или конструктор (Dialog):
Пикассо
Еще одна отличная библиотека с площади. Пожалуйста, смотрите сайт для некоторых замечательных примеров: http://square.github.io/picasso/
источник
Проще говоря,
НЕ СЕТЬ РАБОТАЙТЕ В РЕЗЬБЕ UI
Например, если вы делаете HTTP-запрос, это действие сети.
Решение:
Путь:
Положите все свои работы внутри
run()
метод новой темыdoInBackground()
метод класса AsyncTask.Но:
Когда вы получаете что-то из ответа Сети и хотите показать это в своем представлении (например, отобразить ответное сообщение в TextView), вам нужно вернуться обратно в поток пользовательского интерфейса .
Если вы этого не сделаете, вы получите
ViewRootImpl$CalledFromWrongThreadException
.Как?
onPostExecute()
методаrunOnUiThread()
метод и обновите представление внутриrun()
метода.источник
Вы можете переместить часть своего кода в другой поток, чтобы разгрузить
main thread
и избежать получения ANR , NetworkOnMainThreadException , IllegalStateException (например, Невозможно получить доступ к базе данных в основном потоке, так как это может потенциально заблокировать пользовательский интерфейс на длительный период времени).Есть несколько подходов, которые вы должны выбрать, зависит от ситуации
Java Thread или Android HandlerThread
AsyncTask
Реализация пула потоков ThreadPoolExecutor , ScheduledThreadPoolExecutor ...
FutureTask
AsyncTaskLoaders
IntentService
JobScheduler
RxJava
Сопрограммы (Котлин)
Узнайте больше здесь , здесь , здесь , здесь
источник
Хотя выше есть огромный пул решений, никто не упомянул
com.koushikdutta.ion
: https://github.com/koush/ionЭто также асинхронный и очень простой в использовании:
источник
Новые решения
Thread
и решения AsyncTask уже были объяснены.AsyncTask
в идеале следует использовать для коротких операций. ОбычныйThread
не предпочтителен для Android.Взгляните на альтернативное решение, используя HandlerThread и Handler
HandlerThread
Обработчик:
Решение:
Создайте
HandlerThread
Позвони
start()
наHandlerThread
Создать
Handler
, получаяLooper
отHanlerThread
Вставить код, связанный с вашей сетевой операцией, в
Runnable
объектОтправить
Runnable
задачу вHandler
Пример кода, адрес которого
NetworkOnMainThreadException
Плюсы использования этого подхода:
Thread/AsyncTask
для каждой сети операций обходится дорого.Thread/AsyncTask
Будет разрушен и воссоздан для последующих операций сети. Но при подходеHandler
иHandlerThread
подходе вы можете отправлять множество сетевых операций (как выполняемые задачи) в однуHandlerThread
с помощьюHandler
.источник
Есть еще один очень удобный способ решения этой проблемы - использовать возможности параллелизма rxJava. Вы можете выполнять любую задачу в фоновом режиме и очень удобно размещать результаты в главном потоке, поэтому эти результаты будут переданы в цепочку обработки.
Первый проверенный ответ - использовать AsynTask. Да, это решение, но в настоящее время оно устарело, потому что вокруг появились новые инструменты.
Метод getUrl предоставляет URL-адрес, и он будет выполняться в основном потоке.
makeCallParseResponse (..) - выполняет реальную работу
processResponse (..) - обработает результат в основном потоке.
Код для асинхронного выполнения будет выглядеть так:
По сравнению с AsyncTask этот метод позволяет переключать планировщики произвольное количество раз (скажем, извлекать данные из одного планировщика и обрабатывать эти данные из другого (скажем, Scheduler.computation ()). Вы также можете определить свои собственные планировщики.
Чтобы использовать эту библиотеку, включите в файл build.gradle следующие строки:
Последняя зависимость включает поддержку планировщика .mainThread ().
Есть отличная книга для rx-java .
источник
RxAndroid
Это еще одна лучшая альтернатива этой проблеме, которая избавляет нас от хлопот, связанных с созданием потоков и публикацией результатов в потоке пользовательского интерфейса Android. Нам просто нужно указать потоки, в которых должны выполняться задачи, и все обрабатывается внутренне.По specifiying
(Schedulers.io())
, RxAndroid будет работатьgetFavoriteMusicShows()
на другом потоке.Используя это,
AndroidSchedulers.mainThread()
мы хотим наблюдать это Observable в потоке пользовательского интерфейса, т.е. мы хотим, чтобы нашonNext()
обратный вызов вызывался в потоке пользовательского интерфейса.источник
Основной поток является потоком пользовательского интерфейса, и вы не можете выполнить в основном потоке операцию, которая может заблокировать взаимодействие с пользователем. Вы можете решить это двумя способами:
Заставить сделать задачу в главном потоке вот так
Или создайте простой обработчик и обновите основной поток, если хотите.
И чтобы остановить поток, используйте:
Для получения дополнительной информации проверьте это: безболезненный поток
источник
Это работает. Просто сделал ответ доктора Луиджи немного проще.
источник
На Android сетевые операции не могут выполняться в главном потоке. Вы можете использовать Thread, AsyncTask (краткосрочные задачи), Service (долгосрочные задачи) для выполнения сетевых операций.
источник