thread networkonmainthreadexception network fatal example error caused asynctask java android networkonmainthread thread-exceptions

java - fatal - caused by android os networkonmainthreadexception



¿Cómo corrijo android.os.NetworkOnMainThreadException? (30)

  1. No use strictMode (solo en el modo de depuración)
  2. No cambie la versión del SDK
  3. No utilice un hilo separado

Use Service o AsyncTask

Véase también la pregunta sobre el desbordamiento de pila:

android.os.NetworkOnMainThreadException enviando un correo electrónico desde Android

Recibí un error mientras ejecutaba 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?


Deshabilitas el modo estricto usando el siguiente código:

if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }

Esto no es recomendable : use la interfaz AsyncTask .

Código completo para ambos métodos.


El error se debe a la ejecución de operaciones de larga ejecución en el subproceso principal. Puede corregir fácilmente el problema utilizando AsynTask o Thread . Puede retirar esta biblioteca AsyncHTTPClient para un mejor manejo.

AsyncHttpClient client = new AsyncHttpClient(); client.get("http://www.google.com", new AsyncHttpResponseHandler() { @Override public void onStart() { // Called before a request is started } @Override public void onSuccess(int statusCode, Header[] headers, byte[] response) { // Called when response HTTP status is "200 OK" } @Override public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) { // Called when response HTTP status is "4XX" (for example, 401, 403, 404) } @Override public void onRetry(int retryNo) { // Called when request is retried } });


En palabras simples,

NO HAGA TRABAJOS DE RED EN LA UI HILO

Por ejemplo, si realiza una solicitud HTTP, es una acción de red.

Solución:

  1. Tienes que crear un nuevo hilo.
  2. O use la clase AsyncTask

Camino:

Pon todos tus trabajos dentro

  1. run() método de nuevo hilo
  2. O el método doInBackground() de la clase AsyncTask.

Pero:

Cuando obtiene algo de la respuesta de la 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, obtendrás ViewRootImpl$CalledFromWrongThreadException .

¿Cómo?

  1. Mientras usa AsyncTask, actualice la vista desde el método onPostExecute()
  2. O llame runOnUiThread() método runOnUiThread() y actualice la vista dentro del método run() .

Esta excepción se produce cuando una aplicación intenta realizar una operación de red en su hilo principal. Ejecuta tu código en AsyncTask :

class RetrieveFeedTask extends AsyncTask<String, Void, RSSFeed> { private Exception exception; protected RSSFeed doInBackground(String... urls) { try { URL url = new URL(urls[0]); 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(); } catch (Exception e) { this.exception = e; return null; } finally { is.close(); } } protected void onPostExecute(RSSFeed feed) { // TODO: check this.exception // TODO: do something with the feed } }

Cómo ejecutar la tarea:

En el archivo MainActivity.java puede agregar esta línea dentro de su método oncreate()

new RetrieveFeedTask().execute(urlToRssFeed);

No olvide agregar esto al archivo AndroidManifest.xml :

<uses-permission android:name="android.permission.INTERNET"/>


Esta excepción se produce debido a cualquier tarea pesada realizada en el subproceso principal si la tarea que realiza lleva demasiado tiempo .

Para evitar esto, podemos manejarlo utilizando hilos o ejecutores.

Executors.newSingleThreadExecutor().submit(new Runnable() { @Override public void run() { // You can perform your task here. } });



Esto sucede en Android 3.0 y superior. Desde Android 3.0 y superiores, han restringido el uso de operaciones de red (funciones que acceden a Internet) para que no se ejecuten en el hilo principal / subproceso 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 fomentar el uso de subprocesos separados para las operaciones de red. Consulte AsyncTask para obtener más detalles sobre cómo realizar las actividades de la red de la manera correcta.


Hacer las acciones de red en otro hilo.

Por ejemplo:

new Thread(new Runnable(){ @Override public void run() { // Do network action in this function } }).start();

Y agrega esto a AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET"/>


La respuesta superior de spektom funciona perfecto.

Si escribe AsyncTask línea y no se extiende como una clase, y además de esto, si es necesario obtener una respuesta de AsyncTask , puede usar el método get() como se muestra a continuación.

RSSFeed feed = new RetreiveFeedTask().execute(urlToRssFeed).get();

(De su ejemplo).


La respuesta aceptada tiene algunas desventajas significativas. No es recomendable usar AsyncTask para redes a menos que realmente sepa lo que está haciendo. Algunas de las desventajas incluyen:

  • Las clases de AsyncTask creadas como no internas estáticas tienen una referencia implícita al objeto de Actividad adjunto, su contexto y toda la jerarquía de la vista creada por esa actividad. Esta referencia evita que la Actividad se recoja como basura hasta que finalice el trabajo en segundo plano de AsyncTask. Si la conexión del usuario es lenta y / o la descarga es grande, estas pérdidas de memoria a corto plazo pueden convertirse en un problema, por ejemplo, si la orientación cambia varias veces (y no cancela las tareas en ejecución), o el usuario navega fuera de la actividad.
  • AsyncTask tiene diferentes características de ejecución en función de la plataforma en la que se ejecuta: antes del nivel 4 de API, las AsyncTasks se ejecutan en serie en un solo hilo de fondo; desde el nivel de API 4 hasta el nivel de API 10, AsyncTasks se ejecuta en un grupo de hasta 128 subprocesos; a partir del nivel de API 11, AsyncTask se ejecuta en serie en un solo hilo de fondo (a menos que use el método executeOnExecutor sobrecargado y suministre 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 inadvertidas de orden de ejecución.

Si desea evitar las 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:

  1. Usar una biblioteca que haga un buen trabajo de esto para usted: hay una buena comparación de librerías de redes en esta pregunta , o
  2. IntentService lugar, IntentService un Service o IntentService , quizás con un PendingIntent para devolver el resultado a través del método onActivityResult la Actividad.

Enfoque IntentService

Lados bajos

  • Más código y complejidad que AsyncTask , aunque no tanto como podría pensar.
  • Encolará las solicitudes y las ejecutará en un único hilo de fondo. Puede controlar esto fácilmente reemplazando IntentService con una implementación de Service equivalente, tal como esta .
  • Um, no puedo pensar en ningún otro en este momento en realidad

Lados superiores

  • Evita el problema de pérdida de memoria a corto plazo.
  • Si su actividad se reinicia mientras las operaciones de la red están en vuelo, aún puede recibir el resultado de la descarga a través de su método onActivityResult
  • Mejor plataforma que AsyncTask para crear y reutilizar código de red robusto. Ejemplo: si necesita realizar una carga importante, puede hacerlo desde AsyncTask en una Activity , pero si el usuario cambia de contexto fuera de la aplicación para tomar una llamada telefónica, el sistema puede matar la aplicación antes de que se complete la carga. Es menos probable que mate una aplicación con un Service activo.
  • Si usa su propia versión concurrente de IntentService (como la que he enlazado anteriormente), puede controlar el nivel de concurrencia a través del Executor .

Resumen de implementación

Puede implementar un IntentService para realizar descargas en un solo hilo de fondo con bastante facilidad.

Paso 1: Crea un IntentService para realizar la descarga. Puede decirle qué descargar a través de Intent extra y pasarle un PendingIntent para que devuelva el resultado a la Activity :

import android.app.IntentService; import android.app.PendingIntent; import android.content.Intent; import android.util.Log; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; public class DownloadIntentService extends IntentService { private static final String TAG = DownloadIntentService.class.getSimpleName(); public static final String PENDING_RESULT_EXTRA = "pending_result"; public static final String URL_EXTRA = "url"; public static final String RSS_RESULT_EXTRA = "url"; public static final int RESULT_CODE = 0; public static final int INVALID_URL_CODE = 1; public static final int ERROR_CODE = 2; private IllustrativeRSSParser parser; public DownloadIntentService() { super(TAG); // make one and re-use, in the case where more than one intent is queued parser = new IllustrativeRSSParser(); } @Override protected void onHandleIntent(Intent intent) { PendingIntent reply = intent.getParcelableExtra(PENDING_RESULT_EXTRA); InputStream in = null; try { try { URL url = new URL(intent.getStringExtra(URL_EXTRA)); IllustrativeRSS rss = parser.parse(in = url.openStream()); Intent result = new Intent(); result.putExtra(RSS_RESULT_EXTRA, rss); reply.send(this, RESULT_CODE, result); } catch (MalformedURLException exc) { reply.send(INVALID_URL_CODE); } catch (Exception exc) { // could do better by treating the different sax/xml exceptions individually reply.send(ERROR_CODE); } } catch (PendingIntent.CanceledException exc) { Log.i(TAG, "reply cancelled", exc); } } }

Paso 2: Registrar el servicio en el manifiesto:

<service android:name=".DownloadIntentService" android:exported="false"/>

Paso 3: Invoque el servicio de la Actividad, pasando un objeto PendingResult que el Servicio utilizará para devolver el resultado:

PendingIntent pendingResult = createPendingResult( RSS_DOWNLOAD_REQUEST_CODE, new Intent(), 0); Intent intent = new Intent(getApplicationContext(), DownloadIntentService.class); intent.putExtra(DownloadIntentService.URL_EXTRA, URL); intent.putExtra(DownloadIntentService.PENDING_RESULT_EXTRA, pendingResult); startService(intent);

Paso 4: Manejar el resultado en onActivityResult:

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RSS_DOWNLOAD_REQUEST_CODE) { switch (resultCode) { case DownloadIntentService.INVALID_URL_CODE: handleInvalidURL(); break; case DownloadIntentService.ERROR_CODE: handleError(data); break; case DownloadIntentService.RESULT_CODE: handleRSS(data); break; } handleRSS(data); } super.onActivityResult(requestCode, resultCode, data); }

Un proyecto github que contiene un proyecto completo de Android-Studio / gradle en funcionamiento está disponible here .


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 ejecutas una tarea en un subproceso secundario:

new Thread(new Runnable(){ @Override public void run() { try { // Your implementation goes here } catch (Exception ex) { ex.printStackTrace(); } } }).start();


No debe realizar tareas que requieran mucho tiempo en el subproceso principal (subproceso UI), como cualquier operación de red, E / S de archivos o operaciones de base de datos SQLite. Por lo tanto, 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 el Message .

Para simplificar todas estas cosas, Android proporciona varias formas, como AsyncTask , AsyncTaskLoader , CursorLoader o IntentService . Así que puedes usar cualquiera de estos de acuerdo a tus requerimientos.


No puede realizar I/O red en el subproceso de la interfaz de usuario en Honeycomb . Técnicamente, es posible en versiones anteriores de Android, pero es una muy mala idea ya que hará que la aplicación deje de responder y puede hacer que el sistema operativo anule su aplicación por mal comportamiento. Deberá ejecutar un proceso en segundo plano o usar AsyncTask para realizar su transacción de red en un hilo en segundo plano.

Hay un artículo sobre Painless Threading en el sitio del desarrollador de Android que es una buena introducción a esto, y le proporcionará una respuesta mucho más profunda de lo que se puede proporcionar de manera realista aquí.


Para mi fue esto:

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="10" />

El dispositivo en el que estaba probando mi aplicación era 4.1.2, que es la versión 16 del SDK.

Asegúrese de que la versión de destino sea la misma que la 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 Proyecto -> Crear ruta -> Android , y debería ser el que está marcado.

Además, como han mencionado otros, incluya los permisos correctos para acceder a Internet:

<uses-permission android:name="android.permission.INTERNET"/>


Ponga su código dentro:

new Thread(new Runnable(){ @Override public void run() { try { // Your implementation } catch (Exception ex) { ex.printStackTrace(); } } }).start();

O:

class DemoTask extends AsyncTask<Void, Void, Void> { protected Void doInBackground(Void... arg0) { //Your implementation } protected void onPostExecute(Void result) { // TODO: do something with the feed } }


Resolví este problema usando un nuevo Thread .

Thread thread = new Thread(new Runnable() { @Override public void run() { try { //Your code goes here } catch (Exception e) { e.printStackTrace(); } } }); thread.start();


Solo para deletrear algo explícitamente:

El hilo principal es básicamente el hilo de la interfaz de usuario.

Entonces, decir que no puede realizar operaciones de red en el hilo principal significa que no puede realizar operaciones de red en el hilo de la interfaz de usuario, lo que significa que no puede realizar operaciones de red en un *runOnUiThread(new Runnable() { ... }* dentro de otro hilo) , ya sea.

(Acabo de pasar un largo momento de rascarme la cabeza tratando de averiguar por qué estaba teniendo ese error en algún lugar que no sea mi hilo principal. Por eso; este hilo ayudó; y espero que este comentario ayude a otra persona).


Usar Anotaciones de Android es una opción. Te permitirá simplemente ejecutar cualquier método en un hilo de fondo:

// normal method private void normal() { doSomething(); // do something in background } @Background protected void doSomething() // run your networking code here }

Tenga en cuenta que, aunque proporciona beneficios de simplicidad y legibilidad, tiene sus desventajas.


Ya hay muchas respuestas excelentes sobre esta pregunta, pero han surgido muchas bibliotecas excelentes desde que se publicaron esas respuestas. Esto está pensado como 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

Digamos que está escribiendo una aplicación que permite a los usuarios realizar un seguimiento de los precios de las acciones, las tasas de interés y las tasas de cambio de moneda. Encuentras una API de Json que se parece a esto:

http://api.example.com/stocks //ResponseWrapper<String> object containing a list of Srings with ticker symbols http://api.example.com/stocks/$symbol //Stock object http://api.example.com/stocks/$symbol/prices //PriceHistory<Stock> object http://api.example.com/currencies //ResponseWrapper<String> object containing a list of currency abbreviation http://api.example.com/currencies/$currency //Currency object http://api.example.com/currencies/$id1/values/$id2 //PriceHistory<Currency> object comparing the prices of the first currency (id1) to the second (id2)

Retrofit de la plaza

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?

construir.gradle

Agregue estas líneas a su nivel de módulo buid.gradle:

implementation ''com.squareup.retrofit2:retrofit:2.3.0'' //retrofit library, current as of September 21, 2017 implementation ''com.squareup.retrofit2:converter-gson:2.3.0'' //gson serialization and deserialization support for retrofit, version must match retrofit version

FinanzasApi.java

public interface FinancesApi { @GET("stocks") Call<ResponseWrapper<String>> listStocks(); @GET("stocks/{symbol}") Call<Stock> getStock(@Path("symbol")String tickerSymbol); @GET("stocks/{symbol}/prices") Call<PriceHistory<Stock>> getPriceHistory(@Path("symbol")String tickerSymbol); @GET("currencies") Call<ResponseWrapper<String>> listCurrencies(); @GET("currencies/{symbol}") Call<Currency> getCurrency(@Path("symbol")String currencySymbol); @GET("currencies/{symbol}/values/{compare_symbol}") Call<PriceHistory<Currency>> getComparativeHistory(@Path("symbol")String currency, @Path("compare_symbol")String currencyToPriceAgainst); }

FinanzasApiBuilder

public class FinancesApiBuilder { public static FinancesApi build(String baseUrl){ return new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .build() .create(FinancesApi.class); } }

Finanzas Fragmento de fragmentos

FinancesApi api = FinancesApiBuilder.build("http://api.example.com/"); //trailing ''/'' required for predictable behavior api.getStock("INTC").enqueue(new Callback<Stock>(){ @Override public void onResponse(Call<Stock> stockCall, Response<Stock> stockResponse){ Stock stock = stockCall.body(); //do something with the stock } @Override public void onResponse(Call<Stock> stockCall, Throwable t){ //something bad happened } }

Si su API requiere que se envíe una Clave de API u otro encabezado como un token de usuario, etc., Retrofit lo hace fácil (consulte esta increíble respuesta para obtener más información: https://.com/a/42899766/1024412 ).

Un solo acceso a la API de ReST

Digamos que está creando una aplicación de "clima del clima" que busca la ubicación de GPS de los usuarios, verifica la temperatura actual en esa área y les dice el estado de ánimo. Este tipo de aplicación no necesita declarar puntos finales de API; solo necesita poder acceder a un punto final de API.

Ion

Esta es una gran biblioteca para este tipo de acceso.

Por favor, lea la gran respuesta de msysmilu ( https://.com/a/28559884/1024412 )

Cargar imágenes a través de HTTP

Voleo

Volley también se puede usar para ReST API, pero debido a la configuración más complicada que se requiere, prefiero usar Retrofit from Square como se indica 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.

construir.gradle

Agregue esta línea a su nivel de módulo buid.gradle:

implementation ''com.android.volley:volley:1.0.0''

ImageFetch.java

Volley requiere más configuración que Retrofit. Necesitará crear una clase como esta para configurar un RequestQueue, un ImageLoader y un ImageCache, pero no está tan mal:

public class ImageFetch { private static ImageLoader imageLoader = null; private static RequestQueue imageQueue = null; public static ImageLoader getImageLoader(Context ctx){ if(imageLoader == null){ if(imageQueue == null){ imageQueue = Volley.newRequestQueue(ctx.getApplicationContext()); } imageLoader = new ImageLoader(imageQueue, new ImageLoader.ImageCache() { Map<String, Bitmap> cache = new HashMap<String, Bitmap>(); @Override public Bitmap getBitmap(String url) { return cache.get(url); } @Override public void putBitmap(String url, Bitmap bitmap) { cache.put(url, bitmap); } }); } return imageLoader; } }

user_view_dialog.xml

Agregue lo siguiente a su archivo xml de diseño para agregar una imagen:

<com.android.volley.toolbox.NetworkImageView android:id="@+id/profile_picture" android:layout_width="32dp" android:layout_height="32dp" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" app:srcCompat="@android:drawable/spinner_background"/>

UserViewDialog.java

Agregue el siguiente código al método onCreate (Fragmento, Actividad) o al constructor (Diálogo):

NetworkImageView profilePicture = view.findViewById(R.id.profile_picture); profilePicture.setImageUrl("http://example.com/users/images/profile.jpg", ImageFetch.getImageLoader(getContext());

Picasso

Otra excelente biblioteca de plaza. Consulte el sitio para ver algunos ejemplos excelentes: http://square.github.io/picasso/


RxAndroides otra alternativa mejor a este problema y nos ahorra las molestias de crear subprocesos y luego publicar resultados en el subproceso de la interfaz de usuario de Android. Solo necesitamos especificar subprocesos en los que las tareas deben ejecutarse y todo se maneja internamente.

Observable<List<String>> musicShowsObservable = Observable.fromCallable(new Callable<List<String>>() { @Override public List<String> call() { return mRestClient.getFavoriteMusicShows(); } }); mMusicShowSubscription = musicShowsObservable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<String>>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(List<String> musicShows){ listMusicShows(musicShows); } });

  1. Por precisaraÂn (Schedulers.io()), RxAndroid se ejecutará getFavoriteMusicShows()en un subproceso diferente.

  2. Al utilizar AndroidSchedulers.mainThread()queremos observar este Observable en el subproceso de la interfaz de usuario, es decir, queremos onNext()que se llame a nuestra devolución de llamada en el subproceso de la interfaz de usuario


Casi siempre debe ejecutar las operaciones de red en un hilo o como una tarea asíncrona.

Pero es posible eliminar esta restricción y anular el comportamiento predeterminado, si está dispuesto a aceptar las consecuencias.

Añadir:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);

En tu clase,

y

AGREGUE este permiso en el archivo manifest.xml de Android:

<uses-permission android:name="android.permission.INTERNET"/>

Consecuencias:

Su aplicación (en áreas de conexión irregular de Internet) dejará de responder y se bloqueará, el usuario percibe la lentitud y tiene que hacer una matanza forzosa, y se arriesga a que el administrador de actividades mate su aplicación y le diga 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


Aunque arriba hay un grupo de soluciones enorme, nadie menciona com.koushikdutta.ion: https://github.com/koush/ion

También es asíncrono y muy simple de usar:

Ion.with(context) .load("http://example.com/thing.json") .asJsonObject() .setCallback(new FutureCallback<JsonObject>() { @Override public void onCompleted(Exception e, JsonObject result) { // do stuff with the result or error } });


El acceso a los recursos de red desde el subproceso principal (UI) provoca esta excepción. Utilice un hilo separado o AsyncTask para acceder a un recurso de red para evitar este problema.


En Android, las operaciones de red no se pueden ejecutar en el hilo principal. Puede usar Thread, AsyncTask (tareas de ejecución corta), Service (tareas de ejecución prolongada) para realizar operaciones de red.


Esto funciona. Acabo de hacer la respuesta del Dr. Luiji un poco más simple.

new Thread() { @Override public void run() { try { //Your code goes here } catch (Exception e) { e.printStackTrace(); } } }.start();


Hay otra manera muy conveniente de abordar este problema: usar las capacidades de concurrencia de rxJava. Puede ejecutar cualquier tarea en segundo plano y publicar los 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 está obsoleta hoy en día, porque hay nuevas herramientas alrededor.

String getUrl() { return "SomeUrl"; } private Object makeCallParseResponse(String url) { return null; // } private void processResponse(Object o) { }

El método getUrl proporciona la dirección URL y se ejecutará en el hilo principal.

makeCallParseResponse (..) - hace el trabajo real

processResponse (..) - manejará el resultado en el hilo principal.

El código para la ejecución asíncrona se verá así:

rx.Observable.defer(new Func0<rx.Observable<String>>() { @Override public rx.Observable<String> call() { return rx.Observable.just(getUrl()); } }) .subscribeOn(Schedulers.io()) .observeOn(Schedulers.io()) .map(new Func1<String, Object>() { @Override public Object call(final String s) { return makeCallParseResponse(s); } }) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<Object>() { @Override public void call(Object o) { processResponse(o); } }, new Action1<Throwable>() { @Override public void call(Throwable throwable) { // Process error here, it will be posted on // the main thread } });

En comparación con AsyncTask, este método permite cambiar los programadores un número arbitrario de veces (por ejemplo, obtener 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:

compile ''io.reactivex:rxjava:1.1.5'' compile ''io.reactivex:rxandroid:1.2.0''

La última dependencia incluye soporte para el programador .mainThread ().

Hay un excelente libro electrónico para rx-java .


No está permitido implementar operaciones de red en el subproceso de la interfaz de usuario en Android. Tendrá que usar la clase AsyncTask para realizar operaciones relacionadas con la red como enviar solicitudes de API, descargar imágenes de una URL, etc. y usar los métodos de devolución de llamada de AsyncTask, puede obtener el resultado en el método onPostExecute y estará en el subproceso de la interfaz de usuario. puede llenar la interfaz de usuario con datos del servicio web o algo así.

Ejemplo: Supongamos que desea descargar una imagen desde una URL: https://www.samplewebsite.com/sampleimage.jpg

Solución utilizando AsyncTask: son respectivamente.

public class MyDownloader extends AsyncTask<String,Void,Bitmap> { @Override protected void onPreExecute() { // Show progress dialog super.onPreExecute(); } @Override protected void onPostExecute(Bitmap bitmap) { //Populate Ui super.onPostExecute(bitmap); } @Override protected Bitmap doInBackground(String... params) { // Open URL connection read bitmaps and return form here return result; } @Override protected void onProgressUpdate(Void... values) { // Show progress update super.onProgressUpdate(values); } } }

Nota: No olvide agregar el permiso de Internet en el archivo de manifiesto de Android. Funcionará a la perfección. :)


Nuevos Thready AsynTask soluciones que ya se han explicado.

AsyncTaskidealmente debería ser utilizado para operaciones cortas. Normal Threadno es preferible para Android.

Eche un vistazo a una solución alternativa utilizando HandlerThread y Handler

HandlerThread

Clase práctica para comenzar un nuevo hilo que tiene un looper. El looper se puede usar para crear clases de manejador. Tenga en cuenta que start()todavía debe ser llamado.

Entrenador de animales:

Un controlador le permite enviar y procesar objetos Message y Runnable asociados con MessageQueue de un subproceso. Cada instancia de Handler está asociada con un solo hilo y la cola de mensajes de ese hilo. Cuando crea un nuevo Controlador, está vinculado a la hebra / cola de mensajes de la hebra que lo está creando; a partir de ese momento, entregará mensajes y se podrá ejecutar en esa cola de mensajes y los ejecutará a medida que salen del mensaje. cola.

Solución:

  1. Crear HandlerThread

  2. Llamar start()alHandlerThread

  3. Crear Handlerobteniendo LooperdeHanlerThread

  4. Incruste el código relacionado con su operación de red en el Runnableobjeto

  5. Enviar Runnabletarea aHandler

Fragmento de código de muestra, cuya dirección NetworkOnMainThreadException

HandlerThread handlerThread = new HandlerThread("URLConnection"); handlerThread.start(); handler mainHandler = new Handler(handlerThread.getLooper()); Runnable myRunnable = new Runnable() { @Override public void run() { try { Log.d("Ravi", "Before IO call"); URL page = new URL("http://www.google.com"); StringBuffer text = new StringBuffer(); HttpURLConnection conn = (HttpURLConnection) page.openConnection(); conn.connect(); InputStreamReader in = new InputStreamReader((InputStream) conn.getContent()); BufferedReader buff = new BufferedReader(in); String line; while ( (line = buff.readLine()) != null) { text.append(line + "/n"); } Log.d("Ravi", "After IO call"); Log.d("Ravi",text.toString()); }catch( Exception err){ err.printStackTrace(); } } }; mainHandler.post(myRunnable);

Ventajas de utilizar este enfoque:

  1. Crear nuevos Thread/AsyncTaskpara cada operación de red es costoso. Se Thread/AsyncTaskdestruirán y se volverán a crear para las próximas operaciones de la red. Pero con Handlery HandlerThreadenfoque, puede presentar muchas operaciones de red (como tareas ejecutables) a solo HandlerThreadutilizando Handler.

**Use like this in Your Activity** btnsub.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub //Initialize soap request + add parameters SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME1); //Use this to add parameters request.addProperty("pincode",txtpincode.getText().toString()); request.addProperty("bg",bloodgroup.getSelectedItem().toString()); //Declare the version of the SOAP request SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11); envelope.setOutputSoapObject(request); envelope.dotNet = true; try { HttpTransportSE androidHttpTransport = new HttpTransportSE(URL); //this is the actual part that will call the webservice androidHttpTransport.call(SOAP_ACTION1, envelope); // Get the SoapResult from the envelope body. SoapObject result = (SoapObject)envelope.getResponse(); Log.e("result data", "data"+result); SoapObject root = (SoapObject) result.getProperty(0); // SoapObject s_deals = (SoapObject) root.getProperty(0); //SoapObject s_deals_1 = (SoapObject) s_deals.getProperty(0); // System.out.println("********Count : "+ root.getPropertyCount()); value=new ArrayList<Detailinfo>(); for (int i = 0; i < root.getPropertyCount(); i++) { SoapObject s_deals = (SoapObject) root.getProperty(i); Detailinfo info=new Detailinfo(); info.setFirstName( s_deals.getProperty("Firstname").toString()); info.setLastName( s_deals.getProperty("Lastname").toString()); info.setDOB( s_deals.getProperty("DOB").toString()); info.setGender( s_deals.getProperty("Gender").toString()); info.setAddress( s_deals.getProperty("Address").toString()); info.setCity( s_deals.getProperty("City").toString()); info.setState( s_deals.getProperty("State").toString()); info.setPinecode( s_deals.getProperty("Pinecode").toString()); info.setMobile( s_deals.getProperty("Mobile").toString()); info.setEmail( s_deals.getProperty("Email").toString()); info.setBloodgroup( s_deals.getProperty("Bloodgroup").toString()); info.setAdddate( s_deals.getProperty("Adddate").toString()); info.setWaight(s_deals.getProperty("waight").toString()); value.add(info); } } catch (Exception e) { e.printStackTrace(); } Intent inten=new Intent(getApplicationContext(),ComposeMail.class); //intent.putParcelableArrayListExtra("valuesList", value); startActivity(inten); } }).start(); } });