Recibí un error al ejecutar mi proyecto de Android para RssReader.
Código:
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();
Y muestra el siguiente error:
android.os.NetworkOnMainThreadException
¿Cómo puedo solucionar este problema?
java
android
android-networking
networkonmainthread
Bejoy George
fuente
fuente
Respuestas:
Esta excepción se produce cuando una aplicación intenta realizar una operación de red en su hilo principal. Ejecute su código en
AsyncTask
:Cómo ejecutar la tarea:
En el
MainActivity.java
archivo puede agregar esta línea dentro de suoncreate()
métodoNo olvide agregar esto al
AndroidManifest.xml
archivo:fuente
AsyncTask
y se encarga de un cambio de configuración.Casi siempre debe ejecutar operaciones de red en un hilo o como una tarea asincrónica.
Pero es posible eliminar esta restricción y anular el comportamiento predeterminado, si está dispuesto a aceptar las consecuencias.
Añadir:
En tu clase,
y
AGREGAR este permiso en el archivo android manifest.xml:
Consecuencias:
Su aplicación (en áreas de conexión a Internet irregular) dejará de responder y se bloqueará, el usuario percibe la lentitud y tiene que matar a la fuerza, y corre el riesgo de que el administrador de actividades mate su aplicación y le diga al usuario que la aplicación se ha detenido.
Android tiene algunos buenos consejos sobre buenas prácticas de programación para diseñar con capacidad de respuesta: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
fuente
doInBackground
declaración, 2 corchetes de cierre y una llamada aexecute()
). Por otro lado, incluso una sola búsqueda de un sitio como usted menciona trae un retraso significativo en la capacidad de respuesta de la interfaz de usuario. No seas perezosoResolví este problema usando uno nuevo
Thread
.fuente
La respuesta aceptada tiene algunas desventajas significativas. No es aconsejable usar AsyncTask para la creación de redes a menos que realmente sepa lo que está haciendo. Algunos de los inconvenientes incluyen:
executeOnExecutor
método sobrecargado y proporcione un ejecutor alternativo). El código que funciona bien cuando se ejecuta en serie en ICS puede romperse cuando se ejecuta simultáneamente en Gingerbread, por ejemplo, si tiene dependencias involuntarias de orden de ejecución.Si desea evitar pérdidas de memoria a corto plazo, tener características de ejecución bien definidas en todas las plataformas y tener una base para construir un manejo de red realmente robusto, puede considerar:
Service
oIntentService
en su lugar, tal vez con unPendingIntent
a devolver el resultado a través de la ActividadonActivityResult
método.Enfoque de servicio
Desventajas:
AsyncTask
, aunque no tanto como podría pensarIntentService
con unaService
implementación equivalente , tal vez como esta .Alzas:
onActivityResult
métodoAsyncTask
unaActivity
, pero si el usuario cambia de contexto de la aplicación para atender una llamada telefónica, el sistema puede cerrar la aplicación antes de que se complete la carga. Es menos probable que mate una aplicación con un activoService
.IntentService
(como la que he vinculado anteriormente) puede controlar el nivel de concurrencia a través deExecutor
.Resumen de implementación
Puede implementar un
IntentService
para realizar descargas en un solo hilo de fondo con bastante facilidad.Paso 1: Crea una
IntentService
para realizar la descarga. Puede decirle qué descargar a través deIntent
extra, y pasarloPendingIntent
a usar para devolver el resultado aActivity
:Paso 2: Registre el servicio en el manifiesto:
Paso 3: Invoque el servicio desde la Actividad, pasando un objeto PendingResult que el Servicio usará para devolver el resultado:
Paso 4: maneje el resultado en onActivityResult:
Un proyecto de Github que contiene un proyecto completo de Android-Studio / Gradle está disponible aquí .
fuente
IllustrativeRSS
? ¿Qué pasa si no estás trabajando con material RSS?AsyncTask
. El error estaba destinado a evitar que los desarrolladores se retrasen en la interfaz de usuario, no necesariamente para atraerlos a arriesgar la seguridad con un montón de intentos / servicios.No puede realizar E / S de red en el subproceso de interfaz de usuario en Honeycomb . Técnicamente, es posible en versiones anteriores de Android, pero es una muy mala idea, ya que hará que su aplicación deje de responder y puede hacer que el sistema operativo mate su aplicación por mal comportamiento. Deberá ejecutar un proceso en segundo plano o utilizar AsyncTask para realizar su transacción de red en un subproceso en segundo plano.
Hay un artículo sobre el subproceso sin dolor en el sitio para desarrolladores de Android que es una buena introducción a esto, y le proporcionará una respuesta mucho más profunda que la que puede proporcionarse aquí de manera realista.
fuente
Usar servicio o AsyncTask
Consulte también la pregunta de desbordamiento de pila:
android.os.NetworkOnMainThreadException enviando un correo electrónico desde Android
fuente
Hacer las acciones de red en otro hilo
Y agregue esto a AndroidManifest.xml
fuente
Deshabilita el modo estricto con el siguiente código:
Esto no se recomienda : use la
AsyncTask
interfaz.Código completo para ambos métodos
fuente
Las operaciones basadas en la red no se pueden ejecutar en el hilo principal. Debe ejecutar todas las tareas basadas en la red en un subproceso secundario o implementar AsyncTask.
Así es como ejecuta una tarea en un hilo secundario:
fuente
Pon tu código dentro:
O:
fuente
Esto sucede en Android 3.0 y superior. Desde Android 3.0 y superior, han restringido el uso de las operaciones de red (funciones que acceden a Internet) para que no se ejecuten en el hilo principal / hilo de la interfaz de usuario (lo que se genera en los métodos de creación y reanudación de la actividad).
Esto es para alentar el uso de hilos separados para las operaciones de red. Consulte AsyncTask para obtener más detalles sobre cómo realizar actividades de red de la manera correcta.
fuente
Usar las anotaciones de Android es una opción. Le permitirá simplemente ejecutar cualquier método en un hilo de fondo:
Tenga en cuenta que, aunque proporciona beneficios de simplicidad y legibilidad, tiene sus desventajas.
fuente
El error se debe a la ejecución de operaciones de larga ejecución en el subproceso principal. Puede rectificar fácilmente el problema utilizando AsynTask o Thread . Puede retirar esta biblioteca AsyncHTTPClient para un mejor manejo.
fuente
No debe realizar ninguna tarea que requiera mucho tiempo en el subproceso principal (subproceso de interfaz de usuario), como cualquier operación de red, E / S de archivo u operaciones de base de datos SQLite. Entonces, para este tipo de operación, debe crear un subproceso de trabajo, pero el problema es que no puede realizar directamente ninguna operación relacionada con la interfaz de usuario desde su subproceso de trabajo. Para eso, tienes que usar
Handler
y pasar elMessage
.Para simplificar todas estas cosas, Android proporciona varias maneras, como
AsyncTask
,AsyncTaskLoader
,CursorLoader
oIntentService
. Por lo tanto, puede utilizar cualquiera de estos según sus requisitos.fuente
La mejor respuesta de spektom funciona perfecta.
Si está escribiendo el en
AsyncTask
línea y no se extiende como una clase, y además de esto, si es necesario obtener una respuestaAsyncTask
, puede usar elget()
método que se muestra a continuación.(De su ejemplo).
fuente
get()
es una mala idea ... hace que AsyncTask vuelva a "sincronizarse"Esto solo se lanza para aplicaciones dirigidas al Honeycomb SDK o superior. Las aplicaciones que se dirigen a versiones anteriores de SDK pueden hacer redes en sus principales hilos de bucle de eventos.
¡El error es la advertencia del SDK!
fuente
Para mí fue esto:
¡El dispositivo en el que estaba probando mi aplicación era 4.1.2, que es SDK Versión 16!
Asegúrese de que la versión de destino sea la misma que su Biblioteca de destino de Android. Si no está seguro de cuál es su biblioteca de destino, haga clic con el botón derecho en su Proyecto -> Crear ruta -> Android , y debería ser la que esté marcada.
Además, como otros han mencionado, incluya los permisos correctos para acceder a Internet:
fuente
NetworkOnMainThreadException
es The Guardian que te dice: no dispares a tu propio pie ... tu solución es: volvamos al pasado cuando no había Guardian, ahora puedo disparar a mi pie librementeUse esto en su actividad
fuente
Solo para explicar algo explícitamente:
El hilo principal es básicamente el hilo de la interfaz de usuario.
Por lo tanto, decir que no puede realizar operaciones de red en el subproceso principal significa que no puede realizar operaciones de red en el subproceso de interfaz de usuario, lo que significa que tampoco puede realizar operaciones de red en un
*runOnUiThread(new Runnable() { ... }*
bloque dentro de otro subproceso.(Acabo de pasar un largo momento tratando de averiguar por qué estaba obteniendo ese error en otro lugar que no sea mi hilo principal. Por eso; este hilo ayudó; y espero que este comentario ayude a alguien más).
fuente
Esta excepción ocurre debido a cualquier tarea pesada realizada en el hilo principal si esa tarea lleva demasiado tiempo .
Para evitar esto, podemos manejarlo usando hilos o ejecutores
fuente
Ya hay muchas respuestas excelentes sobre esta pregunta, pero han surgido muchas bibliotecas excelentes desde que se publicaron esas respuestas. Esto pretende ser una especie de guía para novatos.
Cubriré varios casos de uso para realizar operaciones de red y una solución o dos para cada uno.
ReST sobre HTTP
Típicamente Json, puede ser XML u otra cosa
Acceso completo a la API
Supongamos que está escribiendo una aplicación que permite a los usuarios rastrear los precios de las acciones, las tasas de interés y los tipos de cambio actuales. Encuentra una API de Json que se parece a esto:
Retrofit de Square
Esta es una excelente opción para una API con múltiples puntos finales y le permite declarar los puntos finales ReST en lugar de tener que codificarlos individualmente como con otras bibliotecas como ion o Volley. (sitio web: http://square.github.io/retrofit/ )
¿Cómo se usa con la API de finanzas?
build.gradle
Agregue estas líneas a su nivel de módulo buid.gradle:
FinancesApi.java
FinancesApiBuilder
Fragmento de fragmentos de finanzas
Si su API requiere que se envíe una clave API u otro encabezado como un token de usuario, etc., Retrofit lo hace fácil (consulte esta increíble respuesta para obtener más detalles: https://stackoverflow.com/a/42899766/1024412 ).
Acceso único a la API ReST
Supongamos que está creando una aplicación de "clima meteorológico" que busca la ubicación del GPS del usuario y comprueba la temperatura actual en esa área y les informa el estado de ánimo. Este tipo de aplicación no necesita declarar puntos finales de API; solo necesita poder acceder a un punto final API.
Ion
Esta es una gran biblioteca para este tipo de acceso.
Lea la excelente respuesta de msysmilu ( https://stackoverflow.com/a/28559884/1024412 )
Cargar imágenes a través de HTTP
Voleo
Volley también se puede usar para las API de ReST, pero debido a la configuración más complicada que se requiere, prefiero usar Retrofit from Square como anteriormente ( http://square.github.io/retrofit/ )
Supongamos que está creando una aplicación de red social y desea cargar imágenes de perfil de amigos.
build.gradle
Agregue esta línea a su nivel de módulo buid.gradle:
ImageFetch.java
Volley requiere más configuración que Retrofit. Tendrá que crear una clase como esta para configurar RequestQueue, ImageLoader y ImageCache, pero no está tan mal:
user_view_dialog.xml
Agregue lo siguiente a su archivo xml de diseño para agregar una imagen:
UserViewDialog.java
Agregue el siguiente código al método onCreate (Fragmento, Actividad) o al constructor (Diálogo):
Picasso
Otra excelente biblioteca de Square. Consulte el sitio para ver algunos ejemplos excelentes: http://square.github.io/picasso/
fuente
En palabras simples
NO HAGA TRABAJOS DE RED EN EL HILO UI
Por ejemplo, si realiza una solicitud HTTP, esa es una acción de red.
Solución:
Camino:
Pon todos tus trabajos adentro
run()
método de nuevo hilodoInBackground()
método de la clase AsyncTask.Pero:
Cuando obtiene algo de la respuesta de red y desea mostrarlo en su vista (como mostrar el mensaje de respuesta en TextView), debe volver al hilo de la interfaz de usuario .
Si no lo haces, lo conseguirás
ViewRootImpl$CalledFromWrongThreadException
.¿Cómo?
onPostExecute()
métodorunOnUiThread()
método y actualice la vista dentro delrun()
método.fuente
Puede mover una parte de su código a otro subproceso para descargar
main thread
y evitar ANR , NetworkOnMainThreadException , IllegalStateException (por ejemplo, no se puede acceder a la base de datos en el subproceso principal, ya que puede bloquear la interfaz de usuario durante un largo período de tiempo).Hay algunos enfoques que debe elegir dependiendo de la situación.
Java Thread o Android HandlerThread
AsyncTask
Implementación del grupo de subprocesos ThreadPoolExecutor , ScheduledThreadPoolExecutor ...
FutureTask
AsyncTaskLoaders
IntentService
JobScheduler
RxJava
Corutinas (Kotlin)
Lea más aquí , aquí , aquí , aquí
fuente
Aunque arriba hay un gran grupo de soluciones, nadie mencionó
com.koushikdutta.ion
: https://github.com/koush/ionTambién es asíncrono y muy simple de usar:
fuente
Ya se han explicado las soluciones nuevas
Thread
y AsyncTask .AsyncTask
idealmente debe usarse para operaciones cortas. NormalThread
no es preferible para Android.Eche un vistazo a una solución alternativa usando HandlerThread y Handler
HandlerThread
Manipulador:
Solución:
Crear
HandlerThread
llamar
start()
enHandlerThread
Crear
Handler
obteniendoLooper
deHanlerThread
Incruste su código relacionado con la operación de red en el
Runnable
objetoEnviar
Runnable
tarea aHandler
Fragmento de código de muestra, qué dirección
NetworkOnMainThreadException
Ventajas de usar este enfoque:
Thread/AsyncTask
para cada operación de red es costoso. ElThread/AsyncTask
será destruido y recreado para las próximas operaciones de la red. Pero conHandler
yHandlerThread
enfoque, puede presentar muchas operaciones de red (como tareas ejecutables) a soloHandlerThread
utilizandoHandler
.fuente
Hay otra forma muy conveniente de abordar este problema: utilizar las capacidades de concurrencia de rxJava. Puede ejecutar cualquier tarea en segundo plano y publicar resultados en el hilo principal de una manera muy conveniente, por lo que estos resultados se entregarán a la cadena de procesamiento.
El primer consejo de respuesta verificado es usar AsynTask. Sí, esta es una solución, pero es obsoleta hoy en día, porque existen nuevas herramientas.
El método getUrl proporciona la dirección URL y se ejecutará en el hilo principal.
makeCallParseResponse (..) - funciona realmente
processResponse (..) - manejará el resultado en el hilo principal.
El código para la ejecución asincrónica se verá así:
En comparación con AsyncTask, este método permite cambiar de programador un número arbitrario de veces (por ejemplo, buscar datos en un programador y procesar esos datos en otro (por ejemplo, Scheduler.computation ()). También puede definir sus propios programadores.
Para usar esta biblioteca, incluya las siguientes líneas en su archivo build.gradle:
La última dependencia incluye soporte para el planificador .mainThread ().
Hay un excelente libro electrónico para rx-java .
fuente
RxAndroid
es otra mejor alternativa a este problema y nos salva de las molestias de crear hilos y luego publicar resultados en el hilo de la interfaz de usuario de Android. Solo necesitamos especificar hilos en los que se deben ejecutar las tareas y todo se maneja internamente.Al especificar
(Schedulers.io())
, RxAndroid se ejecutarágetFavoriteMusicShows()
en un hilo diferente.Al usar
AndroidSchedulers.mainThread()
queremos observar este Observable en el hilo de la interfaz de usuario, es decir, queremos que nuestraonNext()
devolución de llamada se invoque en el hilo de la interfaz de usuariofuente
El subproceso principal es el subproceso de interfaz de usuario, y no puede realizar una operación en el subproceso principal que puede bloquear la interacción del usuario. Puedes resolver esto de dos maneras:
Fuerza para hacer la tarea en el hilo principal como este
O cree un controlador simple y actualice el hilo principal si lo desea.
Y para detener el uso del hilo:
Para obtener más información, consulte esto: Roscado sin dolor
fuente
Esto funciona. Acabo de hacer la respuesta del Dr. Luji un poco más simple.
fuente
En Android, las operaciones de red no se pueden ejecutar en el hilo principal. Puede utilizar Thread, AsyncTask (tareas de ejecución corta), Servicio (tareas de ejecución prolongada) para realizar operaciones de red.
fuente